blob: b3b02bd5975454598e456b8cb210959663f953a0 [file] [log] [blame]
/*******************************************************************************
* 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);
}
}