blob: 103bad13aea53f88cd733bdfc951f13677cbff1f [file] [log] [blame]
/*******************************************************************************
* 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.modelquery;
import java.util.List;
import java.util.Vector;
import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.common.contentmodel.CMNode;
import org.eclipse.wst.common.contentmodel.modelqueryimpl.ModelQueryImpl;
import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
import org.eclipse.wst.html.core.HTMLCMProperties;
import org.eclipse.wst.sse.core.modelquery.MovableModelQuery;
import org.eclipse.wst.xml.core.document.XMLElement;
import org.eclipse.wst.xml.uriresolver.util.IdResolver;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
public class HTMLModelQueryImpl extends ModelQueryImpl implements MovableModelQuery {
protected CMDocumentCache fCache = null;
public HTMLModelQueryImpl(CMDocumentCache cache, IdResolver idResolver) {
super(new HTMLModelQueryAssociationProvider(cache, idResolver));
fCache = cache;
}
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++) {
CMElementDeclaration candidate = (CMElementDeclaration) candidates.elementAt(i);
if (candidate == null)
continue;
if (isExcluded(candidate, element))
continue;
content.add(candidate);
}
return content;
}
/**
* @see MovableModelQuery#setIdResolver(IdResolver)
*/
public void setIdResolver(IdResolver 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 XMLElement) {
if (((XMLElement) p).isImplicitTag()) {
p = p.getParentNode();
continue;
}
}
return (Element) p;
}
p = p.getParentNode();
}
return null;
}
/* check the target is implicit elemnt or not */
private static boolean isImplicitElement(Node node) {
if (node.getNodeType() != Node.ELEMENT_NODE)
return false;
if (!(node instanceof XMLElement))
return false;
return ((XMLElement) node).isImplicitTag();
}
}