Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/document/HTMLModelParserAdapter.java')
-rw-r--r--bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/document/HTMLModelParserAdapter.java354
1 files changed, 354 insertions, 0 deletions
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/document/HTMLModelParserAdapter.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/document/HTMLModelParserAdapter.java
new file mode 100644
index 0000000000..e8b4fb3593
--- /dev/null
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/document/HTMLModelParserAdapter.java
@@ -0,0 +1,354 @@
+/*******************************************************************************
+ * 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.wst.html.core.document;
+
+
+
+import org.eclipse.wst.common.contentmodel.CMContent;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMGroup;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.CMNodeList;
+import org.eclipse.wst.html.core.HTML40Namespace;
+import org.eclipse.wst.html.core.HTMLCMProperties;
+import org.eclipse.wst.html.core.contentmodel.HTMLElementDeclaration;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.xml.core.document.TagAdapter;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLText;
+import org.eclipse.wst.xml.core.internal.document.CMNodeUtil;
+import org.eclipse.wst.xml.core.internal.document.ModelParserAdapter;
+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 canContain(Element element, Node child) {
+ if (element == null || child == null)
+ return false;
+ XMLElement impl = (XMLElement) element;
+
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ if (!impl.isGlobalTag())
+ return true; // non HTML tag
+ XMLElement childElement = (XMLElement) 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) {
+ XMLElement parentElement = (XMLElement) 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;
+ XMLElement parentElement = (XMLElement) 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)) {
+ XMLText text = (XMLText) child;
+ if (!text.isWhitespace())
+ 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();
+
+ XMLElement element = (XMLElement) 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(XMLElement 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) {
+ }
+
+ 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();
+ }
+
+} \ No newline at end of file

Back to the top