/******************************************************************************* * Copyright (c) 2004, 2011 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.xml.core.internal.search.matching; import org.eclipse.core.resources.IFile; import org.eclipse.wst.common.core.search.SearchMatch; import org.eclipse.wst.common.core.search.SearchParticipant; import org.eclipse.wst.common.core.search.SearchRequestor; import org.eclipse.wst.common.core.search.pattern.QualifiedName; import org.eclipse.wst.common.core.search.pattern.SearchPattern; import org.eclipse.wst.xml.core.internal.search.XMLComponentSearchPattern; import org.eclipse.wst.xml.core.internal.search.XMLSearchPattern; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; public class XMLSearchPatternMatcher extends PatternMatcher{ /** * The active search participant. */ private SearchParticipant searchParticipant; /** * Constructs a pattern matcher given a search participant. * @param searchParticipant the active {@link SearchParticipant search participant}. */ public XMLSearchPatternMatcher(SearchParticipant searchParticipant) { this.searchParticipant = searchParticipant; } protected String computeNamespaceForPrefix(Element element, String prefix) { String result = null; for (Node node = element; node != null; node = node.getParentNode()) { if (node.getNodeType() == Node.ELEMENT_NODE) { Element e = (Element)node; String attributeName = (prefix != null && prefix.length() > 0) ? ("xmlns:" + prefix) : "xmlns"; //$NON-NLS-1$ //$NON-NLS-2$ result = e.hasAttribute(attributeName) ? e.getAttribute(attributeName) : null; if (result != null && result.length() > 0) { break; } } } return result; } protected void initialize(XMLSearchPattern pattern, Element domElement) { pattern.setElementName(domElement.getLocalName()); pattern.setElementNamespace(domElement.getNamespaceURI()); // TODO (cs) set the depth attribute on the pattern // String actualValue = domElement.hasAttribute(pattern.getAttributeName()) ? domElement.getAttribute(pattern.getAttributeName()) : null; if(actualValue != null && actualValue.length() > 0){ pattern.setSearchElement(domElement); pattern.setSearchName(actualValue); pattern.setSearchNamespace(domElement.getOwnerDocument().getDocumentElement().getAttribute("targetNamespace")); // set a default } } protected void initialize(XMLSearchPattern pattern, SAXSearchElement saxElement) { pattern.setElementName(saxElement.getElementName()); pattern.setElementNamespace(saxElement.getElementNamespace()); pattern.setDepth(saxElement.getDepth()); pattern.setParentName(saxElement.getParentName()); String actualValue = saxElement.getAttributes().getValue(pattern.getAttributeName()); if(actualValue != null){ pattern.setSearchElement(saxElement); pattern.setSearchName(actualValue); pattern.setSearchNamespace(saxElement.getTargetNamespace()); // set a default } } XMLSearchPattern searchPattern; public XMLSearchPatternMatcher() { super(); } /** * This method does dive actual match location to the requestor if there are matches */ public void locateMatches(SearchPattern pattern, IFile file, Element element, SearchRequestor requestor) { if(pattern instanceof XMLComponentSearchPattern){ XMLSearchPattern[] childPatterns = ((XMLComponentSearchPattern)pattern).getChildren(searchParticipant); if (childPatterns == null){ return; } for (int i = 0; i < childPatterns.length; i++) { PatternMatcher matcher = (PatternMatcher)childPatterns[i].getAdapter(PatternMatcher.class); if(matcher == null){ matcher = this; } if(matcher != null){ matcher.locateMatches(childPatterns[i], file, element, requestor); } } } else if(pattern instanceof XMLSearchPattern){ if(matches(pattern, element)){ Attr attribute = element.getAttributeNode(((XMLSearchPattern)pattern).getAttributeName()); addMatch(pattern, file, attribute, requestor); } } } /** * This method only answers if the pattern matches element, it does not give actual match location */ public boolean matches(SearchPattern pattern, Object element){ if(pattern instanceof XMLComponentSearchPattern){ XMLSearchPattern[] childPatterns = ((XMLComponentSearchPattern)pattern).getChildren(searchParticipant); if (childPatterns == null){ return false; } for (int i = 0; i < childPatterns.length; i++) { PatternMatcher matcher = (PatternMatcher)childPatterns[i].getAdapter(PatternMatcher.class); if(matcher == null){ matcher = this; } if(matcher != null){ if(matcher.matches(childPatterns[i], element)){ return true; } } } } else if(pattern instanceof XMLSearchPattern){ XMLSearchPattern possibleMatch = new XMLSearchPattern(); possibleMatch.setAttributeName(((XMLSearchPattern)pattern).getAttributeName()); if(element instanceof Element){ initialize(possibleMatch, (Element)element); } else if(element instanceof SAXSearchElement){ initialize(possibleMatch, (SAXSearchElement)element); } searchPattern = (XMLSearchPattern)pattern; return matchesPattern(possibleMatch); } return false; } protected boolean matchesPattern(SearchPattern pattern) { if(searchPattern != null && pattern instanceof XMLSearchPattern){ XMLSearchPattern decodedPattern = (XMLSearchPattern)pattern; if(searchPattern.getElementName().equals(decodedPattern.getElementName()) && searchPattern.getElementNamespace().equals(decodedPattern.getElementNamespace())){ if(searchPattern.getParentName() != null && decodedPattern.getParentName() != null && !searchPattern.getParentName().equals(decodedPattern.getParentName())) { return false; } return searchPattern.matches(decodedPattern); } } return false; } protected SearchMatch createSearchMatch(IFile file, Attr attributeNode) { SearchMatch match = super.createSearchMatch(file, attributeNode); // todo... remove this ugly hack!! if ("name".equals(attributeNode.getName())) //$NON-NLS-1$ { QualifiedName qualifiedName = new QualifiedName("todo-compute-targetNamespace", attributeNode.getValue()); //$NON-NLS-1$ match.map.put("name", qualifiedName); //$NON-NLS-1$ } //Element element = attributeNode.getOwnerDocument().getDocumentElement(); //if (element.getAttribute("targetNamespace")) //{ //} return match; } }