/******************************************************************************* * 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(); } }