/******************************************************************************* * Copyright © 2000, 2013 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.edt.ide.core.internal.bindings; import java.util.ArrayList; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.edt.compiler.internal.util.EGLFileExtensionUtility; import org.eclipse.edt.ide.core.internal.utils.PatternMatcher; /** * This class is used to resolve the import statements of a file to the * actual files in the Eclipse Workspace. This class will only * match import statments to files that exist. If a file cannot * be found it is just skipped. * * Creation date: (9/4/2001 2:00:57 PM) * @author: David Charboneau */ public class WorkspaceImportResolver extends AbstractImportResolver{ /** * projects - the projects to search for the import statements */ private IProject[] projects = new IProject[0]; /*** * resolvedImports - flag to keep track of when the imports need to be resolved */ private boolean resolvedImports = false; /** * ImportResolver constructor comment. */ public WorkspaceImportResolver(IProject[] projects, String[] imports) { super(imports); if (projects != null) { setProjects(projects); resolvedImports = false; } } /** * Given a list of projects and a list of import statements, this method will * go through all of the projects and find the files that are listed in the import * statments. * * Creation date: (9/4/2001 2:09:14 PM) * @return com.ibm.etools.egl.internal.core.image.common.impl.IFileHandle[] * @param projects com.ibm.etools.egl.internal.core.image.common.impl.IProjectHandle[] * @param imports java.lang.String[] */ private IFile[] doResolveImports() { ArrayList imports = (ArrayList) getImportContainers(); ArrayList unresolvedImports = new ArrayList(); if (!resolvedImports) { for(int i=0; i<imports.size(); i++) { boolean resolvedImport = false; AbstractImportContainer nextImport = (AbstractImportContainer)imports.get(i); for(int j=0; j<projects.length; j++) { resolvedImport = doResolveImports(nextImport, projects[j]); if(resolvedImport) { break; } } if(!resolvedImport && !importHasWildcard(nextImport)) { unresolvedImports.add(imports.get(i)); } } } setUnresolvedImports(unresolvedImports); return (IFile[]) getResolvedImports().toArray(new IFile[getResolvedImports().size()]); } /** * Given a list of projects and a list of import statements, this method will * go through all of the projects and find the files that are listed in the import * statments. * * Creation date: (9/4/2001 2:09:14 PM) * @return com.ibm.etools.egl.internal.core.image.common.impl.IFileHandle[] * @param projects com.ibm.etools.egl.internal.core.image.common.impl.IProjectHandle[] * @param imports java.lang.String[] */ private boolean doResolveImports(AbstractImportContainer importContainer, IResource resource) { boolean resolvedImport = false; if (resource.getType() == IResource.PROJECT) { IResource[] members = null; try { members = ((IContainer) resource).members(); } catch (CoreException ce) { } if (members != null) { for (int i = 0; i < members.length; i++) { resolvedImport = doResolveImports(importContainer, members[i]); if(resolvedImport) { break; } } } } else if(resource.getType() == IResource.FOLDER) { String[] iFolderSegments = getFolderSegments((IFolder) resource); String[] importFolderSegments = getFolderSegments(importContainer); // if the current folder we are in is "shorter" than the folder we // are looking for (i.e. we are in "folderA" and we are looking for // "folderA/folderB") AND the current folder path matches the corresponding // folder path from the import (i.e. using the example above, we are in "folderA" // and it matches the corresponding segments of the import, which is "folderA" of "folderA/folderB"), // keep looking for the import (note: if the segment length is ==, we should be // in the resource.getType() == IResource.FILE code below) if(iFolderSegments.length <= importFolderSegments.length && isMatchingFolder(iFolderSegments, importFolderSegments)) { IResource[] members = null; try { members = ((IContainer) resource).members(); } catch (CoreException ce) { } if (members != null) { for (int i = 0; i < members.length; i++) { resolvedImport = doResolveImports(importContainer, members[i]); if(resolvedImport) { break; } } } } } else if (resource.getType() == IResource.FILE) { IFile file = (IFile) resource; if(isMatchingFolder(getFolderStringForFile(file), importContainer.getFolder())) { if(isMatchingFile(file, importContainer.getFile())) { // store file if it isn't a duplicate if (!isDuplicateImport((IFile) file)) { storeFile(file); } // only report it as resolved if we don't have a wildcard if(!importHasWildcard(importContainer)) { resolvedImport = true; } } } } return resolvedImport; } /** * Compare all of the iFolderSegments with iFolderSegments.length segments * of importFolderSegments. * @param iFolderSegments * @param importFolderSegments * @param i * @return boolean */ private boolean isMatchingFolder( String[] iFolderSegments, String[] importFolderSegments) { boolean result = false; String iFolderString = ""; //$NON-NLS-1$ String importFolderString = ""; //$NON-NLS-1$ if(importFolderSegments.length >= iFolderSegments.length) { for(int i=0; i<iFolderSegments.length; i++) { iFolderString += iFolderSegments[i]; importFolderString += importFolderSegments[i]; } result = isMatchingFolder(iFolderString, importFolderString); } else { // shouldn't get here result = false; } return result; } /** * Given this import container, create an array of strings for each segment * in the folder. * Method getFolderSegments. * @param importContainer * @return String[] */ private String[] getFolderSegments(AbstractImportContainer importContainer) { IPath folderPath = new Path(importContainer.getFolder()); return folderPath.segments(); } /** * iterate backwards from this folder to the project, recording * all folders until we get to the project. * @param iFolder * @return String[] */ private String[] getFolderSegments(IFolder iFolder) { ArrayList result = new ArrayList(); IResource resource = iFolder; while(!(resource instanceof IProject)) { result.add(0, resource.getName()); resource = resource.getParent(); } return (String[])result.toArray(new String[result.size()]); } /** * Insert the method's description here. * Creation date: (9/5/2001 5:04:10 PM) * @return boolean * @param file com.ibm.etools.egl.internal.core.image.common.impl.IFileHandle[] */ private boolean isDuplicateImport(IFile file) { boolean duplicate = false; if (getHashedImports().contains(file.getProjectRelativePath())) { duplicate = true; } return duplicate; } /** * Given a list of projects and a list of import statements, this method will * go through all of the projects and find the files that are listed in the import * statments. * * Creation date: (9/4/2001 2:09:14 PM) * @return com.ibm.etools.egl.internal.core.image.common.impl.IFileHandle[] * @param projects com.ibm.etools.egl.internal.core.image.common.impl.IProjectHandle[] * @param imports java.lang.String[] */ public IFile[] resolveImports() { return doResolveImports(); } /** * Insert the method's description here. * Creation date: (9/6/2001 9:55:57 AM) * @param newProjects com.ibm.etools.egl.internal.core.image.common.impl.IProjectHandle[] */ private void setProjects(IProject[] newProjects) { projects = newProjects; } /** * Insert the method's description here. * Creation date: (9/5/2001 5:06:33 PM) * @param file com.ibm.etools.egl.internal.core.image.common.impl.IFileHandle */ private void storeFile(IFile file) { if (file.getFileExtension() != null && file.getFileExtension().equalsIgnoreCase(EGLFileExtensionUtility.getEGLBuildFileExtension()) ) { getResolvedImports().add(file); getHashedImports().add(file.getProjectRelativePath()); } } /** * @see com.ibm.etools.edt.common.internal.bindings.AbstractImportResolver#getNewImportContainer(String) */ protected AbstractImportContainer getNewImportContainer(String importString) { return new WorkspaceImportContainer(importString); } /** * Given a file resource, get its folder * @param file * @return IFolder */ private String getFolderStringForFile(IFile file) { IPath folderPath = file.getParent().getFullPath(); String result = ""; //$NON-NLS-1$ if(folderPath.segmentCount() > 0) { // remove the Project segment folderPath = folderPath.removeFirstSegments(1); } if(folderPath.segmentCount() > 0) { result = folderPath.toString(); } else { result = WorkspaceImportContainer.DEFAULT_FOLDER_NAME; } return result; } /** * Insert the method's description here. * Creation date: (9/5/2001 4:50:15 PM) * @return boolean * @param file com.ibm.etools.egl.internal.core.image.common.impl.IFileHandle * @param fileName java.lang.String */ private boolean isMatchingFile(IFile file, String fileName) { boolean result = false; // compare the file from this import statmenet to each of the files in this folder PatternMatcher fileMatcher = new PatternMatcher(fileName); if(fileMatcher.equals(file.getName())) { result = true; } return result; } /** * Insert the method's description here. * Creation date: (9/5/2001 4:48:36 PM) * @return boolean * @param folder com.ibm.etools.egl.internal.core.image.common.impl.IFolderHandle * @param folderName java.lang.String */ private boolean isMatchingFolder(String folderString, String folderName) { boolean match = false; // compare the folder from the imports to each of the folders in the project PatternMatcher folderMatcher = new PatternMatcher(fixFolderSeparators(folderName)); if(folderMatcher.equals(folderString)) { match = true; } return match; } }