blob: 134e28b0240165587f8df8c17cac7715f0d91240 [file] [log] [blame]
package org.eclipse.wst.xsd.ui.internal.editor.search;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.wst.common.core.search.SearchEngine;
import org.eclipse.wst.common.core.search.SearchMatch;
import org.eclipse.wst.common.core.search.SearchParticipant;
import org.eclipse.wst.common.core.search.SearchPlugin;
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.common.core.search.scope.SearchScope;
import org.eclipse.wst.common.ui.internal.search.dialogs.IComponentList;
import org.eclipse.wst.common.ui.internal.search.dialogs.IComponentSearchListProvider;
import org.eclipse.wst.xml.core.internal.search.XMLComponentDeclarationPattern;
import org.eclipse.wst.xsd.ui.internal.search.IXSDSearchConstants;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDImport;
import org.eclipse.xsd.XSDInclude;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSchemaContent;
import org.eclipse.xsd.XSDSchemaDirective;
public class XSDElementsSearchListProvider implements
IComponentSearchListProvider {
protected XSDSchema[] schemas;
protected IFile currentFile;
// TODO (cs) remove these and use proper search scopes!
//
public static final int ENCLOSING_PROJECT_SCOPE = 0;
public static final int ENTIRE_WORKSPACE_SCOPE = 1;
public XSDElementsSearchListProvider(IFile currentFile,
XSDSchema[] schemas) {
this.schemas = schemas;
this.currentFile = currentFile;
}
public void populateComponentList(IComponentList list, SearchScope scope,
IProgressMonitor pm) {
// we traverse the elements already defined within the visible
// schemas
// we do this in addition to the component search since this should
// execute
// very quickly and there's a good chance the user wants to select an
// element that's
// already imported/included
// TODO (cs) ensure we don't add duplicates when we proceed to use the
// search list
//
for (int i = 0; i < schemas.length; i++) {
XSDSchema schema = schemas[i];
ComponentCollectingXSDVisitor visitor =
new ComponentCollectingXSDVisitor(list);
visitor.visitSchema(schema, true);
}
// finally we call the search API's to do a potentially slow search
if (scope != null) {
populateComponentListUsingSearch(list, scope, pm);
}
}
class ComponentCollectingXSDVisitor {
protected List visitedSchemas = new ArrayList();
IComponentList list;
ComponentCollectingXSDVisitor(IComponentList list) {
this.list = list;
}
public void visitSchema(XSDSchema schema, boolean visitImportedSchema) {
visitedSchemas.add(schema);
for (Iterator contents = schema.getContents().iterator(); contents.hasNext();) {
XSDSchemaContent content = (XSDSchemaContent) contents.next();
if (content instanceof XSDSchemaDirective) {
XSDSchemaDirective schemaDirective = (XSDSchemaDirective) content;
XSDSchema extSchema = schemaDirective.getResolvedSchema();
if (extSchema != null && !visitedSchemas.contains(extSchema)){
if ( schemaDirective instanceof XSDImport && visitImportedSchema){
visitSchema(extSchema, false);
}
else if ( extSchema instanceof XSDInclude || extSchema instanceof XSDImport){
visitSchema(extSchema, false);
}
}
} else if (content instanceof XSDElementDeclaration) {
list.add(content);
}
}
}
}
private void populateComponentListUsingSearch(IComponentList list,
SearchScope scope, IProgressMonitor pm) {
SearchEngine searchEngine = new SearchEngine();
InternalSearchRequestor requestor = new InternalSearchRequestor(list);
findTypes(searchEngine, requestor, scope,
IXSDSearchConstants.ELEMENT_META_NAME);
}
class InternalSearchRequestor extends SearchRequestor {
IComponentList componentList;
InternalSearchRequestor(IComponentList componentList) {
this.componentList = componentList;
}
public void acceptSearchMatch(SearchMatch match) throws CoreException {
// we filter out the matches from the current file since we assume
// the
// info derived from our schema models is more update to date
// (in the event that we haven't saved our latest modifications)
//
if (match.getFile() != currentFile) {
// TODO... this ugly qualified name stashing will go away soon
//
QualifiedName qualifiedName = null;
Object o = match.map.get("name");
if (o != null && o instanceof QualifiedName) {
qualifiedName = (QualifiedName) o;
}
if (qualifiedName != null
&& qualifiedName.getLocalName() != null) {
componentList.add(match);
}
}
}
}
protected void findTypes(SearchEngine searchEngine,
SearchRequestor requestor, SearchScope scope, QualifiedName metaName) {
try {
XMLComponentDeclarationPattern pattern = new XMLComponentDeclarationPattern(
new QualifiedName("*", "*"), metaName,
SearchPattern.R_PATTERN_MATCH);
// TODO (cs) revist this... we shouldn't be needing to hard-code
// partipant id's
// All we're really doing here is trying to avoid finding matches in
// wsdl's since we don't
// ever want to import/include a wsdl from a schema! Maybe we should
// just scope out any file
// types that aren't xsd's using a custom SearchScope?
//
SearchParticipant particpant = SearchPlugin.getDefault()
.getSearchParticipant(
"org.eclipse.wst.xsd.search.XSDSearchParticipant");
Assert.isNotNull(particpant);
SearchParticipant[] participants = { particpant };
searchEngine.search(pattern, requestor, participants, scope, null,
new NullProgressMonitor());
} catch (CoreException e) {
e.printStackTrace();
}
}
}