[283155] HTML Smart Insert closes tags that should have no end tag
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
index 5950b8a..d824b6c 100644
--- 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
@@ -22,16 +22,26 @@
 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;
 
 /**
@@ -138,9 +148,13 @@
 					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;
+					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;
+					}
 				}
 				
 			}
@@ -223,6 +237,60 @@
 		}
 		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