Bug 125582 - [Wizards] WizardResourceImportPage's contructor does not attempt to find a common IContainer amongst multiple selected resources.
Summary: [Wizards] WizardResourceImportPage's contructor does not attempt to find a co...
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.2   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Platform UI Triaged CLA
QA Contact:
URL:
Whiteboard: hasPatch
Keywords:
Depends on:
Blocks:
 
Reported: 2006-01-27 17:02 EST by Dominique Emond CLA
Modified: 2019-09-06 16:19 EDT (History)
2 users (show)

See Also:


Attachments
Patch for org\eclipse\ui\dialogs\WizardResourceImportPage.java (10.10 KB, patch)
2006-02-01 15:24 EST, Dominique Emond CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dominique Emond CLA 2006-01-27 17:02:19 EST
WizardResourceImportPage's contructor does not attempt to find a common IContainer amongst multiple selected  resources. 

Eclipse: 3.2M4
Plugin:  org.eclipse.ui.ide
Class:   org\eclipse\ui\dialogs\WizardResourceImportPage.java

Here is the REVISED constructor, and a new method, getCommonIResource(), for
your consideration:

//// CODE - START
    /**
     * Creates an import wizard page. If the initial resource selection 
     * contains exactly one container resource then it will be used as the default
     * import destination. Otherwise, if the initial resource selection consists of many resources,
     * a common container resource will be determined and used as
     * the default import destination.
     *
     * @param name the name of the page
     * @param selection the current resource selection
     */
    protected WizardResourceImportPage(String name,
            IStructuredSelection selection) {
        super(name);

        
        //Initialize to null
        currentResourceSelection = null;
        
        if (selection.size() > 0){
        	
        
	        if (selection.size() == 1) {
	            Object firstElement = selection.getFirstElement();
	            if (firstElement instanceof IAdaptable) {
	                Object resource = ((IAdaptable) firstElement)
	                        .getAdapter(IResource.class);
	                if (resource != null)
	                    currentResourceSelection = (IResource) resource;
	            }
	            
		        if (currentResourceSelection != null) {
		            if (currentResourceSelection.getType() == IResource.FILE)
		                currentResourceSelection = currentResourceSelection.getParent();
		
		            if (!currentResourceSelection.isAccessible())
		                currentResourceSelection = null;
		        }
	            
	        }
	        else {
	        	//selection.size() > 1
	   
	        	//attempt to find a common IContainer among all selected resources. Otherwise
	        	//return null
	        	
	        	currentResourceSelection = getCommonIResource(selection);
	        	if (currentResourceSelection != null) {
		            if (!currentResourceSelection.isAccessible())
		                currentResourceSelection = null;
	        	}//if
	        }
	

        }//if

        

    }

    /**
     *  
     * This method will attempt to return an IContainer common to all selected resources.
     * If there is no common IContainer, it will return a null
     * 
     * @param selection the current resource selection
     */
    
    protected IResource getCommonIResource(IStructuredSelection selection) {
    	
    	IResource commonIResource = null;
    	
    	IResource someIResource = null;
    	ArrayList resources = new ArrayList();
        Object selected = null;
        Object resource = null;
        boolean resourcesResideInSameProject = false;

        Hashtable uniqueProjects = new Hashtable();
        String projectName = null;
        
        if ( (selection != null) && (selection.size() > 1) ) {
        	
	     try {

	    	  //First, get the IResource for this selection; if it exists
	    	  //Second, if the IResource is an IFile, get its container instead
	    	  //Third, determine if these IResources have a common project
		
	    	  Iterator it = selection.iterator();
	    	  while(it.hasNext()) {
	    		  selected = it.next();
		          if (selected instanceof IAdaptable) {
		              resource = ((IAdaptable) selected).getAdapter(IResource.class);
		              if (resource != null) {
		                  someIResource = (IResource) resource;
		                  if (someIResource.getType() == IResource.FILE){
		                	  resources.add(someIResource.getParent());
		                  }//if
		                  else {
		                	  resources.add(someIResource);
		                  }//endif
		                  
		                  //keep track of unique project names
		                  projectName = someIResource.getProject().getName();
		                  if (!uniqueProjects.containsKey( projectName )) {
		                	  uniqueProjects.put(projectName, projectName);
		                  }//if
		              }//if
		          }//if
		          
	    	  }//while
	    	  
	    	  
	    	  if (resources.size() > 1) {
	    		  
	    		  
		    	  //
		    	  //figure out if resources all reside in same project
		    	  //
		    	  resourcesResideInSameProject = (uniqueProjects.size() == 1);
		    	  uniqueProjects.clear();
		    	  
		    	  if (!resourcesResideInSameProject) {
		    		  //resources do reside in the same project, therefore no common IContainer resource is possible 
	    			  //so return null
	    			  commonIResource = null;
		    	  }//if
		    	  else {
		    		  
		    		  //all the resources reside in the same project
		    		  //now find the longest common path
		    		  
		    		  
		    		  IResource[] theResources = (IResource[])resources.toArray(new IResource[0]);
		    		  resources.clear();
		    		  
		    		  int i = 0;
		    		  int j =0;
		    		  IPath currentPath = null;
		    		  boolean pathSame = true;
		    		  int iSmallestSegmentCount = -1;
		    		  int segmentCount = 0;
		    		  

	    			   //
	    			   //trim the IResource  paths to the smallest segment size before the main comparison starts
	    			   //
	    			   
	    			   //
	    			   // if the resources already have the same segment count then the following code won't affect
	    			   // the resource array elements at all. However, if the segment counts are not identical, then
	    			   // this step is necessary.
	    			  
	    				iSmallestSegmentCount = Integer.MAX_VALUE;

	    				//determine the smallest path segment count among all resources
		    			for(i=0;i<theResources.length;i++){
		    				segmentCount = theResources[i].getFullPath().segmentCount();
		    				if (segmentCount < iSmallestSegmentCount) {
		    					iSmallestSegmentCount = segmentCount;
		    				}//if
		    			}//for


		    		   //reduce all resources to the smallest segment size
		    		   for(i=0;i<theResources.length;i++){
		    			   segmentCount = theResources[i].getFullPath().segmentCount();
		    			   if (segmentCount > iSmallestSegmentCount) {
		    				   for(j=0;j<(segmentCount-iSmallestSegmentCount);j++){
		    					   //modifying array of resources to get parent of this
		    					   //resource and store it in the old position of the child resource
		    					   theResources[i] = theResources[i].getParent();
		    				   }//for
		    			   }//if
		    		   }//for
		    		
		    		   
		    		   //
		    		   // Begin main comparison loop
		    		   //
			    	   boolean commonContainerPathAchieved = false;

			    	   while(!commonContainerPathAchieved) {

		    			   //
		    			   // path segment counts are all the same at this point for all the resources
		    			   //
			    		   
			    		   
	 		    		    //get the path of the first element to use for comparison  
	 		    		    currentPath = theResources[0].getFullPath();
	    				   
				    		//determine if the resources' paths are the same
				    		pathSame = true;
				    		for(i=0;i<theResources.length;i++){
				    				if (!currentPath.equals(theResources[i].getFullPath())) {
				    					pathSame = false;
				    					break;
				    				}//if
				    		}//for
			    		   

			    			if (pathSame == false) {					    		
			    		   
			    				   //
			    				   // get the parents of all the resources and store them in resource array
			    				   //
			    				   for(i=0;i<theResources.length;i++){
			    					   //modifying array of resources to get parent of this
			    					   //resource and store it in the old position of the child resource
			    					   theResources[i] = theResources[i].getParent();
			    				   }//for
			    				   
			    			}//if
			    			else {
			    				//path is finally common across all resources
			    				
			    				//break out of loop
			    				commonContainerPathAchieved = true;
			    			}//endif
			    			
			    		}//while
			    		   
		    		  
		    		  //
		    		  // At this point, all the IContainer elements in the array have the same path
		    		  //
		    		  
    				  //set the commonIResource
	    			  commonIResource = theResources[0];
		    		  
		    		  
		    	  }//endif
		    	  
	    	  }//if
	    	  
	    	}//try
	    	catch(Exception e){
	    		e.printStackTrace();
	    	}//catch
        }//if
        
    	return commonIResource;
    }
    

//// CODE - END
Comment 1 Dominique Emond CLA 2006-02-01 15:24:48 EST
Created attachment 33966 [details]
Patch for org\eclipse\ui\dialogs\WizardResourceImportPage.java
Comment 2 Karice McIntyre CLA 2006-02-01 15:32:55 EST
Could you provide a description of the problem?  
Comment 3 Dominique Emond CLA 2006-02-01 16:39:42 EST
Currently the import wizard will only populate the "Into folder" field 
if 1 resource is pre-selected by the user in a view. (The logic for this
lies in the WizardResourceImportPage constructor).

For a logical element (which uses the new ResourceMapping concept), it is possible for it to be mapped to 1-to-N resources. 

Having said that, what currently happens is when the user selects
1 logical element that has several resources backing it, the WizardResourceImportPage receives a structured selection of size > 1 and the
current code  sets currentResourceSelection to null (basically ignores this selection), and the "Into folder" field stays blank.

The WizardResourceImportPage should really try to determine a container common
to all selected resources. Example : If 2 resources from 1 logical element sit in the same project, then that project should be the common container, and it should show up in the "Into folder". If none can be found (as in the case where 2 logical elements are selected from DIFFERENT projects), only then set currentResourceSelection to null, and cause the "Into folder" field to stay blank.



Comment 4 Karice McIntyre CLA 2006-02-01 17:28:14 EST
Copying Tod, as he has done some of the logical resource changes in the UI.
Comment 5 Karice McIntyre CLA 2006-02-08 10:27:46 EST
I am giving this bug to Tod as he is working on the logical->physical resources problem.
Comment 6 Dominique Emond CLA 2006-02-09 10:45:54 EST
Hi Tod,

We were hoping this fix could make it in mid-Feburary.
Is this possible?

Please advise.

Thank you.  :)
Comment 7 Tod Creasey CLA 2006-02-09 13:27:02 EST
As this is an API change it is pretty late in the game to get this in (API freeze is in 3 hours). Do you need that method to be protected? If it can be private we have more flexibility.
Comment 8 Dominique Emond CLA 2006-02-09 13:48:24 EST
In WizardResourceImportPage, you can make the method private:
as show below:

private IResource getCommonIResource(IStructuredSelection selection) {


That's fine with me.

Thanks.

:)
Comment 9 Tod Creasey CLA 2006-02-09 14:35:53 EST
Why is it you want this behavioural change BTW. We generally do not try to find common parents for something like this as it is so easy to select something that is not what the user wanted. If they have a single selection they are clear.
Comment 10 Dominique Emond CLA 2006-02-09 14:44:20 EST
Hi,

Our reasons are listed in Comment #3.

But to re-iterate briefly...

We want the import wizard activated off  our logical view to behave the "same"
as when activated off the navigator view (non-logical view).

If our single logical element has 2 resources backing it (the user can only
see the single logical element), and the user has it selected before right-clicking and selecting Import..., the user should see the project name of those
2 backing resources in the Into folder; JUST LIKE the user would see the project name of a single resource appear in the Into Folder field of the Import wizard if 1 single file was selected before the wizard was chosen.

Comment 11 Boris Bokowski CLA 2009-11-26 16:19:57 EST
Prakash is now responsible for watching bugs in the [Wizards] component area.
Comment 12 Eclipse Webmaster CLA 2019-09-06 16:19:03 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.