[132756] implement generic search list dialog (more work expected to fine tune this)
diff --git a/plugins/org.eclipse.wst.common.ui/plugin.properties b/plugins/org.eclipse.wst.common.ui/plugin.properties
index b56b65c..2469615 100644
--- a/plugins/org.eclipse.wst.common.ui/plugin.properties
+++ b/plugins/org.eclipse.wst.common.ui/plugin.properties
@@ -85,6 +85,20 @@
 _UI_RADIO_FILE             = Workbench projects
 _UI_RADIO_URL              = HTTP
 
+_UI_LABEL_COMPONENTS				   = Components:
+_UI_LABEL_QUALIFIER					   = Qualifier:
+
+!- component selection dialogs 
+_UI_LABEL_COMPONENT_NAME			   = Component Name:
+_UI_LABEL_MATCHING_COMPONENTS		   = Matching Components:
+_UI_LABEL_SPECIFIED_FILE			   = Specified File
+_UI_LABEL_ENCLOSING_PROJECT			   = Enclosing Project
+_UI_LABEL_WORKSPACE					   = Workspace
+_UI_LABEL_CURRENT_RESOURCE			   = Current Resource
+_UI_LABEL_SEARCH_SCOPE				   = Search Scope
+_UI_LABEL_NARROW_SEARCH_SCOPE_RESOURCE = Use resource view to narrow search scope
+_UI_LABEL_AVAILABLE_TYPES			   = Available Types
+
 !======================================================================================
 !
 ! Here is the list of Error string that have message IDs - make sure they are unique
diff --git a/plugins/org.eclipse.wst.common.ui/plugin.xml b/plugins/org.eclipse.wst.common.ui/plugin.xml
index 69952c5..87acbfb 100644
--- a/plugins/org.eclipse.wst.common.ui/plugin.xml
+++ b/plugins/org.eclipse.wst.common.ui/plugin.xml
@@ -12,4 +12,20 @@
 	</viewPage>
   </extension>
  
+ <!--
+   <extension point="org.eclipse.ui.popupMenus"> 
+      <objectContribution 
+         id="test" 
+         objectClass="org.eclipse.core.resources.IFile">  
+         <action
+            id="testit" 
+            enablesFor="1"
+            style="pulldown"
+            menubarPath="additions"
+            label="TEST SEARCH DIALOG" 
+            class="org.eclipse.wst.common.ui.internal.search.dialogs.Test"> 
+         </action>          
+      </objectContribution>               
+    </extension> 
+ -->
 </plugin>
diff --git a/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ComponentSearchListDialog.java b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ComponentSearchListDialog.java
new file mode 100644
index 0000000..a028b6a
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ComponentSearchListDialog.java
@@ -0,0 +1,650 @@
+/*******************************************************************************
+ * Copyright (c) 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.common.ui.internal.search.dialogs;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.custom.ViewForm;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.wst.common.core.search.scope.SearchScope;
+import org.eclipse.wst.common.ui.internal.UIPlugin;
+
+
+public class ComponentSearchListDialog extends Dialog {
+    private Display display = Display.getCurrent();
+    private String dialogTitle;
+
+    protected ComponentSearchListDialogConfiguration configuration;
+    private List componentTableViewerInput;
+    private List masterComponentList;
+    
+    // widgets
+    protected Composite topComposite;
+    protected Composite bottomComposite; 
+    private String filterTextLabel = "";
+    private String componentListLabel = "Components";
+    private Text textFilter;
+    protected TableViewer componentTableViewer;
+    
+    protected String fileLocationLabel = "Declaration Location:";
+    protected ViewForm fileLocationView;    
+    protected CLabel locationLabel;
+
+    // keep track of the item previously selected in the table
+	private TableItem prevItem;
+	private String prevItemText;
+
+	protected Object componentSelection;
+    protected Object qualifierTextSelection;
+    
+	protected ToolBar filterToolBar;
+	protected ToolItem toolItem;
+	protected MenuManager fMenuManager;
+	
+	protected HashMap TableDecoratorTrackingTool = new HashMap();  
+    private Button newButton;
+ 
+
+	public ComponentSearchListDialog(Shell shell, String dialogTitle, ComponentSearchListDialogConfiguration configuration) {
+        super(shell);
+        setShellStyle(getShellStyle() | SWT.RESIZE);
+        this.dialogTitle = dialogTitle;
+        this.configuration = configuration;
+        componentTableViewerInput = new ArrayList();
+        masterComponentList = new ArrayList();
+        configuration.init(this);
+    }
+    
+
+    /*
+     * This method should be called before createDialogArea(Composite)
+     */
+    public void setComponentTableLabel(String string) {
+        componentListLabel = string;
+    }
+
+    /*
+     * This method should be called before createDialogArea(Composite)
+     */
+    public void setFilterLabel(String string) {
+        filterTextLabel = string;
+    }
+    
+
+	public void create() {
+        super.create();
+        setTextFilterFocus();
+    }
+    
+    protected void setTextFilterFocus() {
+        textFilter.setFocus();        
+    }
+
+    public Control createDialogArea(Composite parent) {
+        getShell().setText(dialogTitle);
+
+        Composite mainComposite = (Composite) super.createDialogArea(parent);
+        GridData gData = (GridData) mainComposite.getLayoutData();
+        gData.heightHint = 500;
+        gData.widthHint = 400;
+
+        // Subclasses may use this Composite to add desired widgets
+        //topComposite = new Composite(mainComposite, SWT.NONE);
+        //topComposite.setLayoutData(new GridData());
+        //topComposite.setLayout(new GridLayout());
+
+        // do we need to introduce a method here to contain this
+        // so we can add different parent other than 'topComposite'
+        Composite filterLabelAndText = new Composite(mainComposite, SWT.NONE);
+        GridLayout layoutFilterLabelAndText = new GridLayout(2, false);
+        layoutFilterLabelAndText.marginWidth = 0;
+        layoutFilterLabelAndText.marginHeight = 0;
+        filterLabelAndText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        filterLabelAndText.setLayout(layoutFilterLabelAndText);
+
+        // Create Text textFilter
+        Label filterLabel = new Label(filterLabelAndText, SWT.NONE);
+        filterLabel.setText(filterTextLabel);// + "(? = any character, * = any string):");
+        GridData filterLabelData = new GridData();
+        filterLabelData.horizontalSpan = 2;
+        filterLabel.setLayoutData(filterLabelData);
+
+        textFilter = new Text(filterLabelAndText, SWT.SINGLE | SWT.BORDER);
+        textFilter.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));        
+        textFilter.addModifyListener(new TextFilterModifyAdapter());
+        GridData textFilterData = new GridData();
+        textFilterData.horizontalAlignment = GridData.FILL;
+        textFilterData.grabExcessHorizontalSpace = true;
+        textFilter.setLayoutData(textFilterData);
+        
+        final INewComponentHandler handler = configuration.getNewComponentHandler();
+        if (handler != null)
+        {  
+           newButton = new Button(filterLabelAndText, SWT.NONE);
+           newButton.setText("New...");  
+           newButton.addSelectionListener(new SelectionListener()
+           {
+
+            public void widgetDefaultSelected(SelectionEvent e)
+            {
+              handler.openNewComponentDialog();              
+            }
+
+            public void widgetSelected(SelectionEvent e)
+            {              
+            }             
+           });                   
+        }
+        
+        //Composite for table viewer
+        Composite tableComp = new Composite(mainComposite, SWT.NONE);
+        GridLayout tableCompLayout = new GridLayout();
+        tableCompLayout.marginWidth = 0;
+        tableCompLayout.marginTop = 0;
+        tableComp.setLayoutData(new GridData(GridData.FILL_BOTH));
+        tableComp.setLayout(tableCompLayout);
+        
+        // Create Component TableViewer
+        createComponentTableViewer(tableComp);
+        componentTableViewer.getTable().addSelectionListener(new SelectionListener(){
+        	// Changing the text for the component selected and display its source
+        	// file in the box under the table viewer
+          
+        	IComponentDescriptionProvider lp = configuration.getDescriptionProvider();        	
+			public void widgetSelected(SelectionEvent e) {				
+				run();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+				run();
+			}
+
+			private void run() {
+				// restores the text of previous item
+				if (prevItem != null && !prevItem.isDisposed()){
+					prevItem.setText(prevItemText);
+				}
+				TableItem[] items = componentTableViewer.getTable().getSelection();
+				Object component = items[0].getData();
+
+				prevItem = items[0];
+				prevItemText = items[0].getText();
+
+				// add clarification for the first selected item
+				items[0].setText(  lp.getName(component) + " - " + 
+    					lp.getQualifier(component));
+
+				IFile file = lp.getFile(component);
+				updateLocationView(file);
+			}
+        });
+
+        configuration.createWidgetAboveQualifierBox(mainComposite);
+        
+        // Create Qualifier List widget
+        Label qualifierLabel = new Label(mainComposite, SWT.NONE);
+        qualifierLabel.setText(UIPlugin.getString("_UI_LABEL_QUALIFIER"));
+		qualifierLabel.setText(fileLocationLabel);
+
+        fileLocationView = new ViewForm(mainComposite, SWT.BORDER | SWT.FLAT );
+        GridData data = new GridData();
+        data.horizontalAlignment = GridData.FILL;
+        data.grabExcessHorizontalSpace = true;
+        data.heightHint = 25;
+        fileLocationView.setLayoutData(data);
+        
+    	locationLabel = new CLabel(fileLocationView, SWT.FLAT);
+        fileLocationView.setContent(locationLabel);
+    	locationLabel.setFont(fileLocationView.getFont());
+
+        configuration.createWidgetBelowQualifierBox(mainComposite);
+        
+        bottomComposite = new Composite(mainComposite, SWT.NONE);
+        bottomComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        bottomComposite.setLayout(new GridLayout());
+
+        // Populate the Component TableViewer via the provider
+        // TODO: Is this the right way to set/get the ContentProvider?
+        componentTableViewer.setContentProvider(new ComponentTableContentProvider());
+        componentTableViewer.setLabelProvider(configuration.getDescriptionProvider().getLabelProvider());
+        componentTableViewer.setSorter(new ViewerSorter());
+        componentTableViewer.setInput(componentTableViewerInput);
+        
+        
+        // TODO (cs) need to do some work to make the default search scope
+        // more well defined, currently the default behaviour is to pass a null
+        // argument in to populateMasterComponentList but we should provide
+        // getters/setters to allow the default to be controlled
+        populateMasterComponentList(null);
+        refreshTableViewer("");
+
+        return mainComposite;
+    }
+    
+    protected TableViewer createFilterMenuAndTableViewer(Composite comp, String title) {
+    	Composite labelAndFilter = new Composite(comp, SWT.NONE);
+    	labelAndFilter.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		GridLayout layout= new GridLayout();
+		layout.numColumns= 2;
+		layout.marginWidth= 0; layout.marginHeight= 0;
+    	labelAndFilter.setLayout(layout);
+    	
+        Label TableLabel = new Label(labelAndFilter, SWT.NONE);
+        TableLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+        TableLabel.setText(title);
+        
+        filterToolBar = new ToolBar(labelAndFilter,SWT.FLAT);
+        configuration.createToolBarItems(filterToolBar);
+
+        TableViewer TableViewer = new TableViewer(new Table(comp, SWT.SINGLE | SWT.BORDER));
+        Control TableWidget = TableViewer.getTable();
+        GridData gd = new GridData(GridData.FILL_BOTH);
+        TableWidget.setLayoutData(gd);
+
+        return TableViewer;
+    }
+    
+    /*
+     * Creates the Component TableViewer.
+     */
+    private void createComponentTableViewer(Composite base) {
+        componentTableViewer = createFilterMenuAndTableViewer(base, componentListLabel);    
+        
+        componentTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+            public void selectionChanged(SelectionChangedEvent event) {
+                //IStructuredSelection structuredSelection = (IStructuredSelection) event.getSelection();
+                //List qualifiers = searchListProvider.getQualifiers(structuredSelection.getFirstElement());
+                //updateQualifierList(qualifiers);
+                updateCanFinish();
+            }
+        });
+    }
+    
+    private void updateLocationView(IFile file) {
+    	//file Path relative to current workspace
+    	if ( file == null ){
+    		locationLabel.setText("");
+    		locationLabel.setImage(null);
+    		return;
+    	}
+    	String filePath = "";
+    	filePath = file.getFullPath().toString();
+        //locationView.redraw();
+        
+        locationLabel.setText(filePath);
+        // TODO.. get an image from the plugin
+        //locationLabel.setImage(plugin.getImage("icons/XSDFile.gif"));
+        //locationView.redraw();
+    }
+    
+    
+    /*
+     * Returns the processed filter text for the Text field.  Inserts a "."
+     * before each supported meta-character.
+     */
+    protected String getProcessedFilterString() {
+        return processFilterString(textFilter.getText());
+    }
+
+    /*
+     * If supported metacharacters are used in the filter string, we need to
+     * insert a "." before each metacharacter.
+     */
+    private String processFilterString(String inputString) {
+        if (!(inputString.equals(""))) {
+            inputString = insertString("*", ".", inputString);
+            inputString = insertString("?", ".", inputString);
+            inputString = inputString + ".*";
+        } else {
+            inputString = ".*";
+        }
+
+        return inputString.toLowerCase();
+    }
+    
+    /*
+     * Helper method to insert a "." before each metacharacter in the
+     * search/filter string.
+     */
+    private String insertString(String target, String newString, String string) {
+        StringBuffer stringBuffer = new StringBuffer(string);
+
+        int index = stringBuffer.indexOf(target);
+        while (index != -1) {
+            stringBuffer = stringBuffer.insert(index, newString);
+            index = stringBuffer.indexOf(target, index + newString.length() + target.length());
+        }
+
+        return stringBuffer.toString();
+    }
+    
+
+
+    /*
+     * Listens to changes made in the text filter widget
+     */
+    private class TextFilterModifyAdapter implements ModifyListener {
+        public void modifyText(ModifyEvent e) {
+            if (e.widget == textFilter) {
+                if (delayedEvent != null) {
+                    delayedEvent.CANCEL = true;
+                }
+
+                delayedEvent = new DelayedEvent();
+                Display.getCurrent().timerExec(400, delayedEvent);
+            }
+        }
+    }
+
+    //TODO... do we really need one instance?
+    private DelayedEvent delayedEvent;
+
+    /*
+     * Update the component TableViewer when the text filter is modified.
+     * Use a DelayedEvent so we don't update on every keystroke.
+     */
+    private class DelayedEvent implements Runnable {
+        public boolean CANCEL = false;
+
+        public void run() {
+            if (!CANCEL) {
+                refreshTableViewer(getProcessedFilterString());
+                
+                // Select first match
+                if (componentTableViewer.getTable().getItemCount() > 0) {
+                    TableItem item = componentTableViewer.getTable().getItems()[0];
+                    TableItem items[] = new TableItem[1];
+                    items[0] = item;
+                    componentTableViewer.getTable().setSelection(items);
+                }
+                
+                // Update qualifierList
+                //IStructuredSelection structuredSelection = (IStructuredSelection) componentTableViewer.getSelection();
+                // TODO ... manage qualifiers
+                //List qualifiers = searchListProvider.getQualifiers(structuredSelection.getFirstElement());
+                //updateQualifierList(qualifiers);
+                
+                updateCanFinish();
+            }
+        }
+    }
+
+    class ComponentList implements IComponentList {
+        private Vector objectVector = new Vector();
+        private long currentChangeCounter = 0;
+        private long lastUpdateTime = 0;
+        
+        public void add(Object o) {
+            objectVector.add(o);
+            currentChangeCounter++;
+            doViewerUpdate();
+        }
+        
+        public void addAll(Collection collection)
+        {
+          objectVector.addAll(collection);
+          currentChangeCounter += collection.size();
+          doViewerUpdate();          
+        }
+        
+        private void doViewerUpdate() {
+            // TODO: Investigate if we should also add a timer condition??
+          //  if (currentChangeCounter >= 10) {
+          //      currentChangeCounter = 0;
+          //      fireUpdateList(this);
+          //  }
+          
+          // cs: yep I think we really do need to use a time based approach
+          //          
+          long time = System.currentTimeMillis();
+          if (time - lastUpdateTime > 300)
+          {
+             lastUpdateTime = time;
+             fireUpdateList(ComponentList.this);                              
+          }          
+        }
+
+        public int size() {
+            return objectVector.size();
+        }
+        
+        public List subList(int startIndex, int endIndex) {
+            return objectVector.subList(startIndex, endIndex);
+        }
+        
+        public Iterator iterator() {
+            return objectVector.iterator();
+        }
+    }
+
+    
+    // this method gets called from a non-ui thread so needs to call
+    // asyncExec to ensure the UI updates happen on the UI thread
+    //
+    protected void fireUpdateList(final ComponentList list) {    
+        Runnable runnable = new Runnable() {
+            public void run(){
+                // add new objects
+                int growingListSize = list.size();
+                int currentSize = masterComponentList.size();
+                if (growingListSize > currentSize) {
+                    masterComponentList.addAll(list.subList(currentSize, growingListSize));
+                }
+
+                refreshTableViewer(getProcessedFilterString());
+            }
+        };
+        display.asyncExec(runnable);        
+    }
+
+    
+    public void updateForFilterChange()
+    {
+      populateMasterComponentList(null);
+      refreshTableViewer(getProcessedFilterString());
+    }  
+    
+    /*
+     * Populate the Component TreeViewer with items.
+     */
+    protected void populateMasterComponentList(final SearchScope searchScope) {
+        masterComponentList.clear();
+        
+        final ComponentList componentList = new ComponentList();
+        
+        // TODO (cs) it doesn't seem to make sennse to do any of the work on the UI thread
+        // I've change the behaviour here to do all of the work in the background
+        //
+        //searchListProvider._populateComponentListQuick(componentList, 0);        
+        Job job = new Job("read components") {
+          protected IStatus run(IProgressMonitor monitor) {
+            try {
+              // this stuff gets executed on a non-UI thread
+              //
+              long time1 = System.currentTimeMillis();
+              configuration.getSearchListProvider().populateComponentList(componentList, searchScope, null);              
+              // Do a final update of our Input for the component tree viewer.
+              fireUpdateList(componentList);
+              long time2 = System.currentTimeMillis();
+              System.out.println("time=" + (time2 - time1) + " items= " + masterComponentList.size());
+            }
+            catch (Exception e) {
+            	e.printStackTrace();
+            }
+            return Status.OK_STATUS;
+          }          
+        };
+        job.schedule();
+    }
+    
+    protected void refreshTableViewer(String filterText) {
+        componentTableViewerInput.clear();
+        ILabelProvider labelProvider = configuration.getDescriptionProvider().getLabelProvider();
+        Pattern regex = Pattern.compile(filterText);
+        Iterator it = masterComponentList.iterator();
+        while (it.hasNext()) {
+            Object item = it.next();
+            String itemString = labelProvider.getText(item);           
+            Matcher m = regex.matcher(itemString.toLowerCase());
+            if (itemString.toLowerCase().startsWith(filterText) || m.matches()) {
+                componentTableViewerInput.add(item);
+            }
+        }
+        
+        componentTableViewer.refresh();
+        decorateTable();
+    }
+    
+    /**
+     * Looking at each item in the Table. If there are other items with same name
+     * , then add extra info (namespace, file) into the the text label of all these
+     * duplicated items.
+     * - This should be called everytime the Table viewer is refreshed..
+     */
+    protected void decorateTable(){
+    	TableDecoratorTrackingTool.clear();
+    	
+    	IComponentDescriptionProvider lp = configuration.getDescriptionProvider();
+
+    	// init the name-duplicates counter
+    	for (int i = 0; i < componentTableViewerInput.size(); i++){
+    		Object currentItem = componentTableViewerInput.get(i);
+    		String name = lp.getName(currentItem);
+    		Integer count = (Integer) TableDecoratorTrackingTool.get(name);
+			if ( count == null){
+    			TableDecoratorTrackingTool.put(name, new Integer(1));
+    		}
+    		else{
+    			TableDecoratorTrackingTool.put(
+    					name, new Integer(count.intValue() + 1));
+    		}
+    	}
+
+    	// Modify/decorate those items in the Table that have duplicated name
+    	TableItem[] items = componentTableViewer.getTable().getItems();
+    	for (int i =0 ; i < items.length; i++){
+    		Object currentItem = items[i].getData();
+    		Integer count = (Integer) TableDecoratorTrackingTool.get(lp.getName(currentItem));
+    		if ( count != null && count.intValue() > 1){	
+    			items[i].setText(lp.getName(currentItem) + " - " + 
+    					lp.getQualifier(currentItem));
+    		}
+    	}
+    }
+    
+
+    
+    /*
+     * If there is a selection in the ComponentTreeViewer, enable OK
+     */
+    protected void updateCanFinish() {
+        IStructuredSelection selection = (IStructuredSelection) componentTableViewer.getSelection();
+        if (selection.getFirstElement() != null) {
+            getButton(IDialogConstants.OK_ID).setEnabled(true);
+        }
+        else {
+            getButton(IDialogConstants.OK_ID).setEnabled(false);
+        }
+    }
+    
+    protected void okPressed() {
+        IStructuredSelection selection = (IStructuredSelection) componentTableViewer.getSelection();
+        componentSelection = selection.getFirstElement();
+        
+        super.okPressed();
+    }
+    
+    private class ComponentTableContentProvider implements ITreeContentProvider {
+        public Object[] getChildren(Object parentElement) {
+            if (parentElement instanceof List) {
+                return ((List) parentElement).toArray();
+            }
+            return new Object[0];
+        }
+        
+        public Object[] getElements(Object inputElement) {
+            return getChildren(inputElement);
+        }
+        
+        public Object getParent(Object element) {
+            return null;
+        }
+        
+        public boolean hasChildren(Object element) {
+            if (getChildren(element).length > 0) {
+                return true;
+            }
+            return false;
+        }
+        
+        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+        }
+        
+        public void dispose() {
+        }
+    }
+
+
+    public ComponentSpecification getSelectedComponent()
+    {
+      ComponentSpecification result = null;
+      if (componentSelection != null)
+      {  
+        result = new ComponentSpecification();
+        IComponentDescriptionProvider componentDescriptionProvider = configuration.getDescriptionProvider();
+        result.setName(componentDescriptionProvider.getName(componentSelection));
+        result.setQualifier(componentDescriptionProvider.getQualifier(componentSelection));
+        result.setFile(componentDescriptionProvider.getFile(componentSelection));
+        result.setObject(componentSelection);
+      }  
+      return result;
+    }       
+}
diff --git a/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ComponentSearchListDialogConfiguration.java b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ComponentSearchListDialogConfiguration.java
new file mode 100644
index 0000000..61b0e24
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ComponentSearchListDialogConfiguration.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 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.common.ui.internal.search.dialogs;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.ToolBar;
+
+public class ComponentSearchListDialogConfiguration
+{
+  IComponentSearchListProvider searchListProvider; 
+  IComponentDescriptionProvider descriptionProvider;
+  INewComponentHandler newComponentHandler;
+  ComponentSearchListDialog dialog;
+
+  public void init(ComponentSearchListDialog dialog)
+  {
+    this.dialog = dialog;
+  }
+  
+  public void createWidgetAboveQualifierBox(Composite parent)
+  {    
+  }
+  public void createWidgetBelowQualifierBox(Composite parent)
+  {    
+  }
+  
+  public void createToolBarItems(ToolBar toolBar)
+  {    
+  }
+
+  public IComponentDescriptionProvider getDescriptionProvider()
+  {
+    return descriptionProvider;
+  }
+
+  public void setDescriptionProvider(IComponentDescriptionProvider descriptionProvider)
+  {
+    this.descriptionProvider = descriptionProvider;
+  }
+
+  public IComponentSearchListProvider getSearchListProvider()
+  {
+    return searchListProvider;
+  }
+
+  public void setSearchListProvider(IComponentSearchListProvider searchListProvider)
+  {
+    this.searchListProvider = searchListProvider;
+  }
+
+  public ComponentSearchListDialog getDialog()
+  {
+    return dialog;
+  }
+
+  public INewComponentHandler getNewComponentHandler()
+  {
+    return newComponentHandler;
+  }
+
+  public void setNewComponentHandler(INewComponentHandler newComponentHandler)
+  {
+    this.newComponentHandler = newComponentHandler;
+  }
+}
diff --git a/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ComponentSpecification.java b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ComponentSpecification.java
new file mode 100644
index 0000000..65abbc4
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ComponentSpecification.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 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.common.ui.internal.search.dialogs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.wst.common.core.search.pattern.QualifiedName;
+
+public class ComponentSpecification
+{
+  String qualifier;
+  String name;
+  IFile file;
+  Object object;
+  boolean isNew;
+  QualifiedName metaName;
+  
+  public ComponentSpecification()
+  {    
+  }
+  
+  public ComponentSpecification(String qualifier, String name, IFile file)
+  {
+    super();
+    this.qualifier = qualifier;
+    this.name = name;
+    this.file = file;
+  }
+
+  public IFile getFile()
+  {
+    return file;
+  }
+
+  public void setFile(IFile file)
+  {
+    this.file = file;
+  }
+
+  public String getName()
+  {
+    return name;
+  }
+
+  public void setName(String name)
+  {
+    this.name = name;
+  }
+
+  public String getQualifier()
+  {
+    return qualifier;
+  }
+
+  public void setQualifier(String qualifier)
+  {
+    this.qualifier = qualifier;
+  }
+
+  public Object getObject()
+  {
+    return object;
+  }
+
+  public void setObject(Object object)
+  {
+    this.object = object;
+  }
+
+  public boolean isNew()
+  {
+    return isNew;
+  }
+
+  public void setNew(boolean isNew)
+  {
+    this.isNew = isNew;
+  }
+
+  public QualifiedName getMetaName()
+  {
+    return metaName;
+  }
+
+  public void setMetaName(QualifiedName metaName)
+  {
+    this.metaName = metaName;
+  }
+}
diff --git a/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/IComponentDescriptionProvider.java b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/IComponentDescriptionProvider.java
new file mode 100644
index 0000000..c4fbc0b
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/IComponentDescriptionProvider.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 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.common.ui.internal.search.dialogs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.viewers.ILabelProvider;
+
+public interface IComponentDescriptionProvider
+{
+  boolean isApplicable(Object component);
+  
+  String getQualifier(Object component);
+
+  String getName(Object component);
+
+  IFile getFile(Object component);
+
+  ILabelProvider getLabelProvider();
+}
diff --git a/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/IComponentList.java b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/IComponentList.java
new file mode 100644
index 0000000..0fa248a
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/IComponentList.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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.common.ui.internal.search.dialogs;
+
+import java.util.Iterator;
+
+public interface IComponentList {
+   public void add(Object o);
+   public Iterator iterator();
+}
diff --git a/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/IComponentSearchListProvider.java b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/IComponentSearchListProvider.java
new file mode 100644
index 0000000..66a79ad
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/IComponentSearchListProvider.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 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.common.ui.internal.search.dialogs;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.common.core.search.scope.SearchScope;
+
+
+public interface IComponentSearchListProvider
+{
+  void populateComponentList(IComponentList list, SearchScope scope, IProgressMonitor pm);
+}
diff --git a/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/INewComponentHandler.java b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/INewComponentHandler.java
new file mode 100644
index 0000000..7a5093f
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/INewComponentHandler.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 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.common.ui.internal.search.dialogs;
+
+public interface INewComponentHandler
+{
+  void openNewComponentDialog();
+}
diff --git a/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ScopedComponentSearchListDialog.java b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ScopedComponentSearchListDialog.java
new file mode 100644
index 0000000..5b2bbb4
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/ScopedComponentSearchListDialog.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * 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.common.ui.internal.search.dialogs;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog;
+import org.eclipse.wst.common.core.search.scope.ProjectSearchScope;
+import org.eclipse.wst.common.core.search.scope.SearchScope;
+//import org.eclipse.wst.common.core.search.scope.WorkingSetSearchScope;
+import org.eclipse.wst.common.core.search.scope.WorkspaceSearchScope;
+import org.eclipse.wst.common.ui.internal.UIPlugin;
+
+public class ScopedComponentSearchListDialog extends ComponentSearchListDialog
+{
+  protected final static String DEFAULT_NAME_FIELD_TITLE = UIPlugin.getString("_UI_LABEL_COMPONENT_NAME");
+  protected final static String DEFAULT_LIST_TITLE = UIPlugin.getString("_UI_LABEL_MATCHING_COMPONENTS");
+  public static final String SCOPE_SPECIFIED_FILE = UIPlugin.getString("_UI_LABEL_SPECIFIED_FILE");
+  public static final String SCOPE_ENCLOSING_PROJECT = UIPlugin.getString("_UI_LABEL_ENCLOSING_PROJECT");
+  public static final String SCOPE_WORKSPACE = UIPlugin.getString("_UI_LABEL_WORKSPACE");
+  public static final String SCOPE_CURRENT_RESOURCE = UIPlugin.getString("_UI_LABEL_CURRENT_RESOURCE");
+  //TODO externalize to UIPlugin
+  public static final String SCOPE_WORKING_SETS = "Working Sets";
+  
+  private String currentSearchScope = SCOPE_CURRENT_RESOURCE;
+  protected Button chooseButton;
+  protected Button[] radioButton = new Button[4];
+  protected String filterLabel;
+  protected String listTitle;
+  protected IResource currentResource;
+  protected Composite selectWorkingSetsGroup;
+  protected Text workingSetsText;
+  
+  // working sets currently chosen by the user
+  private IWorkingSet[] workingSets;
+
+  public ScopedComponentSearchListDialog(Shell shell, String dialogTitle, ComponentSearchListDialogConfiguration configuration)
+  {
+    super(shell, dialogTitle, configuration);
+  }
+  
+  public void setFilterLabel(String filterLabel)
+  {
+    this.filterLabel = filterLabel;
+  }
+  
+  public void setListTitle(String listTitle)
+  {
+    this.listTitle = listTitle;
+  }  
+
+  public Control createDialogArea(Composite parent)
+  {
+    super.setFilterLabel(filterLabel != null ? filterLabel : DEFAULT_NAME_FIELD_TITLE);
+    setComponentTableLabel(listTitle != null ? listTitle : DEFAULT_LIST_TITLE);
+    super.createDialogArea(parent);
+    // We use the Composite topComposite to create additional widgets
+    GridLayout layout = new GridLayout();
+    layout.marginWidth = 0;
+    bottomComposite.setLayout(layout);
+    Group group = new Group(bottomComposite, SWT.NONE);
+    GridLayout gridLayout = new GridLayout(3, false);
+    // gridLayout.marginWidth = 0;
+    // gridLayout.marginLeft = 2;
+    group.setLayout(gridLayout);
+    group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+    group.setText(UIPlugin.getString("_UI_LABEL_SEARCH_SCOPE"));
+    ScopeChangeListener scopeChangeListener = new ScopeChangeListener();
+    radioButton[0] = new Button(group, SWT.RADIO);
+    radioButton[0].setText(SCOPE_WORKSPACE);
+    radioButton[1] = new Button(group, SWT.RADIO);
+    radioButton[1].setText(SCOPE_ENCLOSING_PROJECT);
+    radioButton[2] = new Button(group, SWT.RADIO);
+    radioButton[2].setText(SCOPE_CURRENT_RESOURCE);
+    radioButton[3] = new Button(group, SWT.RADIO);
+    radioButton[3].setText(SCOPE_WORKING_SETS);
+    for (int i = 0; i < radioButton.length; i++)
+    {
+      if (radioButton[i].getText().equals(currentSearchScope))
+      {
+        radioButton[i].setSelection(true);
+      }
+      radioButton[i].addSelectionListener(scopeChangeListener);
+    }
+    
+    selectWorkingSetsGroup = new Composite(group, SWT.NONE);
+	GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+    gd.horizontalSpan = 2;
+    selectWorkingSetsGroup.setLayoutData(gd);
+    GridLayout workingSetGroupLayout = new GridLayout(2, false);
+    workingSetGroupLayout.marginWidth = 0;
+    workingSetGroupLayout.marginHeight = 0;
+    selectWorkingSetsGroup.setLayout(workingSetGroupLayout);
+    
+    workingSetsText = new Text(selectWorkingSetsGroup, SWT.BORDER | SWT.READ_ONLY);
+    workingSetsText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+    
+    chooseButton = new Button(selectWorkingSetsGroup, SWT.NONE);
+    chooseButton.setText("Choose...");
+    chooseButton.addSelectionListener(new SelectionAdapter() {
+		public void widgetSelected(SelectionEvent e) {
+			Shell shell = getShell();
+			IWorkingSetSelectionDialog dialog = PlatformUI.getWorkbench().getWorkingSetManager().createWorkingSetSelectionDialog(shell, true);
+			if ( dialog.open() == Window.OK){
+				workingSets = dialog.getSelection();
+				String names = "";
+				for (int i = 0; i < workingSets.length; i++){
+					names += workingSets[i].getLabel();
+					// if not the last item, we add a comma
+					if ( i != workingSets.length - 1) 
+						names += ", ";
+				}
+				workingSetsText.setText(names);
+			}
+			// Set working sets radio button enabled, disable other buttons
+			radioButton[2].setSelection(false);
+			radioButton[1].setSelection(false);
+			radioButton[0].setSelection(false);
+			radioButton[3].setSelection(true);
+
+			scopeChangeHandler(radioButton[3]);
+		}
+    });
+
+    return parent;
+  } /*
+     * Returns the selected search scope.
+     */
+
+  public String getSearchScope()
+  {
+    return currentSearchScope;
+  }
+
+private void scopeChangeHandler(Button b) {	  
+	  if ((b.getStyle() & SWT.RADIO) != 0)
+	  {
+		  currentSearchScope = b.getText();
+		  
+		  // TODO (cs) need to do some work to make the default search scope
+		  // more well defined, currently the default behaviour is to pass a null
+		  // argument in to populateMasterComponentList but we should provide
+		  // getters/setters to allow the default to be controlled          
+		  SearchScope scope = null;
+		  if (currentSearchScope == SCOPE_ENCLOSING_PROJECT &&
+				  currentResource != null) { 
+			  scope = new ProjectSearchScope(currentResource.getLocation());
+		  } 
+		  else if (currentSearchScope == SCOPE_WORKSPACE){
+			  scope = new WorkspaceSearchScope();
+		  }
+		  else if (currentSearchScope == SCOPE_WORKING_SETS){
+			  /*
+			  // Constructs the working sets scope from the working sets the user
+			  // selected
+			  WorkingSetSearchScope workingSetsScope = new WorkingSetSearchScope();
+			  for (int i = 0; i < workingSets.length; i++){
+				  workingSetsScope.addAWorkingSetToScope(workingSets[i].getElements());
+			  }
+			  
+			  scope = workingSetsScope;
+			  //System.err.println("WS");
+              */
+		  }
+		  
+		  populateMasterComponentList(scope);
+		  refreshTableViewer(getProcessedFilterString());
+		  // Select the first matching component. Though we should be
+		  // smarter here
+		  // and determine if there was a selection before the scope
+		  // switch (and if
+		  // the component is still available.
+		  Table table = componentTableViewer.getTable();
+		  TableItem items[] = table.getItems();
+		  if (items.length > 0)
+		  {
+			  TableItem select[] = new TableItem[1];
+			  select[0] = items[0];
+			  table.setSelection(select);
+		  }
+		  updateCanFinish();
+	  }
+  }
+
+private class ScopeChangeListener extends SelectionAdapter
+  {
+    public void widgetSelected(SelectionEvent e)
+    {
+      if (e.widget instanceof Button)
+      {
+    	Button b = (Button) e.widget;
+        scopeChangeHandler(b);
+      }
+    }
+  }
+
+  public IResource getCurrentResource()
+  {
+    return currentResource;
+  }
+
+  public void setCurrentResource(IResource currentResource)
+  {
+    this.currentResource = currentResource;
+  }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/Test.java b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/Test.java
new file mode 100644
index 0000000..482e254
--- /dev/null
+++ b/plugins/org.eclipse.wst.common.ui/src-search/org/eclipse/wst/common/ui/internal/search/dialogs/Test.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 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.common.ui.internal.search.dialogs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.actions.ActionDelegate;
+import org.eclipse.wst.common.core.search.scope.SearchScope;
+
+public class Test extends ActionDelegate
+{
+  public void run(IAction action)
+  {
+    try
+    {
+      ComponentSearchListDialogConfiguration configuration = new ComponentSearchListDialogConfiguration();
+      configuration.setSearchListProvider(searchListProvider);
+      configuration.setDescriptionProvider(new BaseComponentDescriptionProvider("foo"));
+      Shell shell = Display.getCurrent().getActiveShell();
+      ComponentSearchListDialog dialog = new ComponentSearchListDialog(shell, "test", configuration);
+      dialog.setFilterLabel("Text:");
+      dialog.setBlockOnOpen(true);
+      dialog.create();
+      dialog.open();
+    }
+    catch (Exception e)
+    {
+      e.printStackTrace();
+    }
+  }
+  class BaseComponentDescriptionProvider extends LabelProvider implements IComponentDescriptionProvider
+  {
+    String prefix;
+
+    BaseComponentDescriptionProvider(String prefix)
+    {
+      this.prefix = prefix;
+    }
+
+    public IFile getFile(Object component)
+    {
+      return null;
+    }
+
+    public ILabelProvider getLabelProvider()
+    {
+      return this;
+    }
+
+    public String getName(Object component)
+    {
+      String string = (String) component;
+      return string.substring(prefix.length() + 1);
+    }
+
+    public String getQualifier(Object component)
+    {
+      return prefix;
+    }
+
+    public String getText(Object element)
+    {
+      return getName(element);
+    }
+
+    public boolean isApplicable(Object component)
+    {
+      if (component instanceof String)
+      {
+        return ((String) component).startsWith(prefix);
+      }
+      return false;
+    }
+  }
+  
+  IComponentSearchListProvider searchListProvider = new IComponentSearchListProvider()
+  {
+    public void populateComponentList(IComponentList list, SearchScope scope, IProgressMonitor pm)
+    {
+      list.add("foo:" + "Hello!");
+      list.add("foo:" + "Hey!");
+      list.add("foo:" + "How-are-you?");
+      list.add("foo:" + "What-is-that-smell?");
+    }
+  };
+}
diff --git a/plugins/org.eclipse.wst.common.ui/src/org/eclipse/wst/common/ui/internal/UIPlugin.java b/plugins/org.eclipse.wst.common.ui/src/org/eclipse/wst/common/ui/internal/UIPlugin.java
index c06c011..fafc278 100644
--- a/plugins/org.eclipse.wst.common.ui/src/org/eclipse/wst/common/ui/internal/UIPlugin.java
+++ b/plugins/org.eclipse.wst.common.ui/src/org/eclipse/wst/common/ui/internal/UIPlugin.java
@@ -71,7 +71,11 @@
 			return key;
 		}
 	}
-	
+
+    public static String getString(String key)
+    {
+      return getResourceString(key);     
+    }
 	/**
 	 * This gets the string resource and does one substitution.
 	 */