| /******************************************************************************* |
| * 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.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.provisional.document.IDOMElement; |
| import org.eclipse.wst.xml.core.internal.ssemodelquery.MovableModelQuery; |
| 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, URIResolver 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(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; |
| } |
| |
| } |