<s> package org . eclipse . jdt . core . dom . rewrite ; import java . util . ArrayList ; import java . util . HashMap ; import java . util . List ; import java . util . Map ; import org . eclipse . core . runtime . CoreException ; import org . eclipse . core . runtime . IProgressMonitor ; import org . eclipse . core . runtime . NullProgressMonitor ; import org . eclipse . core . runtime . SubProgressMonitor ; import org . eclipse . jdt . core . Flags ; import org . eclipse . jdt . core . ICompilationUnit ; import org . eclipse . jdt . core . IImportDeclaration ; import org . eclipse . jdt . core . ITypeRoot ; import org . eclipse . jdt . core . JavaCore ; import org . eclipse . jdt . core . JavaModelException ; import org . eclipse . jdt . core . Signature ; import org . eclipse . jdt . core . compiler . CharOperation ; import org . eclipse . jdt . core . dom . * ; import org . eclipse . jdt . internal . core . dom . rewrite . ImportRewriteAnalyzer ; import org . eclipse . jdt . internal . core . util . Messages ; import org . eclipse . jdt . internal . core . util . Util ; import org . eclipse . text . edits . MultiTextEdit ; import org . eclipse . text . edits . TextEdit ; public final class ImportRewrite { public static abstract class ImportRewriteContext { public final static int RES_NAME_FOUND = 1 ; public final static int RES_NAME_UNKNOWN = 2 ; public final static int RES_NAME_CONFLICT = 3 ; public final static int KIND_TYPE = 1 ; public final static int KIND_STATIC_FIELD = 2 ; public final static int KIND_STATIC_METHOD = 3 ; public abstract int findInContext ( String qualifier , String name , int kind ) ; } private static final char STATIC_PREFIX = 's' ; private static final char NORMAL_PREFIX = 'n' ; private final ImportRewriteContext defaultContext ; private final ICompilationUnit compilationUnit ; private final CompilationUnit astRoot ; private final boolean restoreExistingImports ; private final List existingImports ; private final Map importsKindMap ; private String [ ] importOrder ; private int importOnDemandThreshold ; private int staticImportOnDemandThreshold ; private List addedImports ; private List removedImports ; private String [ ] createdImports ; private String [ ] createdStaticImports ; private boolean filterImplicitImports ; private boolean useContextToFilterImplicitImports ; public static ImportRewrite create ( ICompilationUnit cu , boolean restoreExistingImports ) throws JavaModelException { if ( cu == null ) { throw new IllegalArgumentException ( "" ) ; } List existingImport = null ; if ( restoreExistingImports ) { existingImport = new ArrayList ( ) ; IImportDeclaration [ ] imports = cu . getImports ( ) ; for ( int i = 0 ; i < imports . length ; i ++ ) { IImportDeclaration curr = imports [ i ] ; char prefix = Flags . isStatic ( curr . getFlags ( ) ) ? STATIC_PREFIX : NORMAL_PREFIX ; existingImport . add ( prefix + curr . getElementName ( ) ) ; } } return new ImportRewrite ( cu , null , existingImport ) ; } public static ImportRewrite create ( CompilationUnit astRoot , boolean restoreExistingImports ) { if ( astRoot == null ) { throw new IllegalArgumentException ( "" ) ; } ITypeRoot typeRoot = astRoot . getTypeRoot ( ) ; if ( ! ( typeRoot instanceof ICompilationUnit ) ) { throw new IllegalArgumentException ( "" ) ; } List existingImport = null ; if ( restoreExistingImports ) { existingImport = new ArrayList ( ) ; List imports = astRoot . imports ( ) ; for ( int i = 0 ; i < imports . size ( ) ; i ++ ) { ImportDeclaration curr = ( ImportDeclaration ) imports . get ( i ) ; StringBuffer buf = new StringBuffer ( ) ; buf . append ( curr . isStatic ( ) ? STATIC_PREFIX : NORMAL_PREFIX ) . append ( curr . getName ( ) . getFullyQualifiedName ( ) ) ; if ( curr . isOnDemand ( ) ) { if ( buf . length ( ) > 1 ) buf . append ( '.' ) ; buf . append ( '*' ) ; } existingImport . add ( buf . toString ( ) ) ; } } return new ImportRewrite ( ( ICompilationUnit ) typeRoot , astRoot , existingImport ) ; } private ImportRewrite ( ICompilationUnit cu , CompilationUnit astRoot , List existingImports ) { this . compilationUnit = cu ; this . astRoot = astRoot ; if ( existingImports != null ) { this . existingImports = existingImports ; this . restoreExistingImports = ! existingImports . isEmpty ( ) ; } else { this . existingImports = new ArrayList ( ) ; this . restoreExistingImports = false ; } this . filterImplicitImports = true ; this . useContextToFilterImplicitImports = false ; this . defaultContext = new ImportRewriteContext ( ) { public int findInContext ( String qualifier , String name , int kind ) { return findInImports ( qualifier , name , kind ) ; } } ; this . addedImports = null ; this . removedImports = null ; this . createdImports = null ; this . createdStaticImports = null ; this . importOrder = CharOperation . NO_STRINGS ; this . importOnDemandThreshold = 99 ; this . staticImportOnDemandThreshold = 99 ; this . importsKindMap = new HashMap ( ) ; } public void setImportOrder ( String [ ] order ) { if ( order == null ) throw new IllegalArgumentException ( "" ) ; this . importOrder = order ; } public void setOnDemandImportThreshold ( int threshold ) { if ( threshold <= 0 ) throw new IllegalArgumentException ( "" ) ; this . importOnDemandThreshold = threshold ; } public void setStaticOnDemandImportThreshold ( int threshold ) { if ( threshold <= 0 ) throw new IllegalArgumentException ( "" ) ; this . staticImportOnDemandThreshold = threshold ; } public ICompilationUnit getCompilationUnit ( ) { return this . compilationUnit ; } public ImportRewriteContext getDefaultImportRewriteContext ( ) { return this . defaultContext ; } public void setFilterImplicitImports ( boolean filterImplicitImports ) { this . filterImplicitImports = filterImplicitImports ; } public void setUseContextToFilterImplicitImports ( boolean useContextToFilterImplicitImports ) { this . useContextToFilterImplicitImports = useContextToFilterImplicitImports ; } private static int compareImport ( char prefix , String qualifier , String name , String curr ) { if ( curr . charAt ( 0 ) != prefix || ! curr . endsWith ( name ) ) { return ImportRewriteContext . RES_NAME_UNKNOWN ; } curr = curr . substring ( 1 ) ; if ( curr . length ( ) == name . length ( ) ) { if ( qualifier . length ( ) == 0 ) { return ImportRewriteContext . RES_NAME_FOUND ; } return ImportRewriteContext . RES_NAME_CONFLICT ; } int dotPos = curr . length ( ) - name . length ( ) - 1 ; if ( curr . charAt ( dotPos ) != '.' ) { return ImportRewriteContext . RES_NAME_UNKNOWN ; } if ( qualifier . length ( ) != dotPos || ! curr . startsWith ( qualifier ) ) { return ImportRewriteContext . RES_NAME_CONFLICT ; } return ImportRewriteContext . RES_NAME_FOUND ; } final int findInImports ( String qualifier , String name , int kind ) { boolean allowAmbiguity = ( kind == ImportRewriteContext . KIND_STATIC_METHOD ) || ( name . length ( ) == 1 && name . charAt ( 0 ) == '*' ) ; List imports = this . existingImports ; char prefix = ( kind == ImportRewriteContext . KIND_TYPE ) ? NORMAL_PREFIX : STATIC_PREFIX ; for ( int i = imports . size ( ) - 1 ; i >= 0 ; i -- ) { String curr = ( String ) imports . get ( i ) ; int res = compareImport ( prefix , qualifier , name , curr ) ; if ( res != ImportRewriteContext . RES_NAME_UNKNOWN ) { if ( ! allowAmbiguity || res == ImportRewriteContext . RES_NAME_FOUND ) { if ( prefix != STATIC_PREFIX ) { return res ; } Object currKind = this . importsKindMap . get ( curr . substring ( 1 ) ) ; if ( currKind != null && currKind . equals ( this . importsKindMap . get ( qualifier + '.' + name ) ) ) { return res ; } } } } if ( this . filterImplicitImports && this . useContextToFilterImplicitImports ) { String fPackageName = this . compilationUnit . getParent ( ) . getElementName ( ) ; String mainTypeSimpleName = JavaCore . removeJavaLikeExtension ( this . compilationUnit . getElementName ( ) ) ; String fMainTypeName = Util . concatenateName ( fPackageName , mainTypeSimpleName , '.' ) ; if ( kind == ImportRewriteContext . KIND_TYPE && ( qualifier . equals ( fPackageName ) || fMainTypeName . equals ( Util . concatenateName ( qualifier , name , '.' ) ) ) ) return ImportRewriteContext . RES_NAME_FOUND ; } return ImportRewriteContext . RES_NAME_UNKNOWN ; } public Type addImportFromSignature ( String typeSig , AST ast ) { return addImportFromSignature ( typeSig , ast , this . defaultContext ) ; } public Type addImportFromSignature ( String typeSig , AST ast , ImportRewriteContext context ) { if ( typeSig == null || typeSig . length ( ) == 0 ) { throw new IllegalArgumentException ( "" ) ; } int sigKind = Signature . getTypeSignatureKind ( typeSig ) ; switch ( sigKind ) { case Signature . BASE_TYPE_SIGNATURE : return ast . newPrimitiveType ( PrimitiveType . toCode ( Signature . toString ( typeSig ) ) ) ; case Signature . ARRAY_TYPE_SIGNATURE : Type elementType = addImportFromSignature ( Signature . getElementType ( typeSig ) , ast , context ) ; return ast . newArrayType ( elementType , Signature . getArrayCount ( typeSig ) ) ; case Signature . CLASS_TYPE_SIGNATURE : String erasureSig = Signature . getTypeErasure ( typeSig ) ; String erasureName = Signature . toString ( erasureSig ) ; if ( erasureSig . charAt ( 0 ) == Signature . C_RESOLVED ) { erasureName = internalAddImport ( erasureName , context ) ; } Type baseType = ast . newSimpleType ( ast . newName ( erasureName ) ) ; String [ ] typeArguments = Signature . getTypeArguments ( typeSig ) ; if ( typeArguments . length > 0 ) { ParameterizedType type = ast . newParameterizedType ( baseType ) ; List argNodes = type . typeArguments ( ) ; for ( int i = 0 ; i < typeArguments . length ; i ++ ) { String curr = typeArguments [ i ] ; if ( containsNestedCapture ( curr ) ) { argNodes . add ( ast . newWildcardType ( ) ) ; } else { argNodes . add ( addImportFromSignature ( curr , ast , context ) ) ; } } return type ; } return baseType ; case Signature . TYPE_VARIABLE_SIGNATURE : return ast . newSimpleType ( ast . newSimpleName ( Signature . toString ( typeSig ) ) ) ; case Signature . WILDCARD_TYPE_SIGNATURE : WildcardType wildcardType = ast . newWildcardType ( ) ; char ch = typeSig . charAt ( 0 ) ; if ( ch != Signature . C_STAR ) { Type bound = addImportFromSignature ( typeSig . substring ( 1 ) , ast , context ) ; wildcardType . setBound ( bound , ch == Signature . C_EXTENDS ) ; } return wildcardType ; case Signature . CAPTURE_TYPE_SIGNATURE : return addImportFromSignature ( typeSig . substring ( 1 ) , ast , context ) ; default : throw new IllegalArgumentException ( "" + typeSig ) ; } } public String addImport ( ITypeBinding binding ) { return addImport ( binding , this . defaultContext ) ; } public String addImport ( ITypeBinding binding , ImportRewriteContext context ) { if ( binding . isPrimitive ( ) || binding . isTypeVariable ( ) || binding . isRecovered ( ) ) { return binding . getName ( ) ; } ITypeBinding normalizedBinding = normalizeTypeBinding ( binding ) ; if ( normalizedBinding == null ) { return "invalid" ; } if ( normalizedBinding . isWildcardType ( ) ) { StringBuffer res = new StringBuffer ( "?" ) ; ITypeBinding bound = normalizedBinding . getBound ( ) ; if ( bound != null && ! bound . isWildcardType ( ) && ! bound . isCapture ( ) ) { if ( normalizedBinding . isUpperbound ( ) ) { res . append ( " extends " ) ; } else { res . append ( " super " ) ; } res . append ( addImport ( bound , context ) ) ; } return res . toString ( ) ; } if ( normalizedBinding . isArray ( ) ) { StringBuffer res = new StringBuffer ( addImport ( normalizedBinding . getElementType ( ) , context ) ) ; for ( int i = normalizedBinding . getDimensions ( ) ; i > 0 ; i -- ) { res . append ( "[]" ) ; } return res . toString ( ) ; } String qualifiedName = getRawQualifiedName ( normalizedBinding ) ; if ( qualifiedName . length ( ) > 0 ) { String str = internalAddImport ( qualifiedName , context ) ; ITypeBinding [ ] typeArguments = normalizedBinding . getTypeArguments ( ) ; if ( typeArguments . length > 0 ) { StringBuffer res = new StringBuffer ( str ) ; res . append ( '<' ) ; for ( int i = 0 ; i < typeArguments . length ; i ++ ) { if ( i > 0 ) { res . append ( ',' ) ; } ITypeBinding curr = typeArguments [ i ] ; if ( containsNestedCapture ( curr , false ) ) { res . append ( '?' ) ; } else { res . append ( addImport ( curr , context ) ) ; } } res . append ( '>' ) ; return res . toString ( ) ; } return str ; } return getRawName ( normalizedBinding ) ; } private boolean containsNestedCapture ( ITypeBinding binding , boolean isNested ) { if ( binding == null || binding . isPrimitive ( ) || binding . isTypeVariable ( ) ) { return false ; } if ( binding . isCapture ( ) ) { if ( isNested ) { return true ; } return containsNestedCapture ( binding . getWildcard ( ) , true ) ; } if ( binding . isWildcardType ( ) ) { return containsNestedCapture ( binding . getBound ( ) , true ) ; } if ( binding . isArray ( ) ) { return containsNestedCapture ( binding . getElementType ( ) , true ) ; } ITypeBinding [ ] typeArguments = binding . getTypeArguments ( ) ; for ( int i = 0 ; i < typeArguments . length ; i ++ ) { if ( containsNestedCapture ( typeArguments [ i ] , true ) ) { return true ; } } return false ; } private boolean containsNestedCapture ( String signature ) { return signature . length ( ) > 1 && signature . indexOf ( Signature . C_CAPTURE , 1 ) != - 1 ; } private static ITypeBinding normalizeTypeBinding ( ITypeBinding binding ) { if ( binding != null && ! binding . isNullType ( ) && ! "void" . equals ( binding . getName ( ) ) ) { if ( binding . isAnonymous ( ) ) { ITypeBinding [ ] baseBindings = binding . getInterfaces ( ) ; if ( baseBindings . length > 0 ) { return baseBindings [ 0 ] ; } return binding . getSuperclass ( ) ; } if ( binding . isCapture ( ) ) { return binding . getWildcard ( ) ; } return binding ; } return null ; } public Type addImport ( ITypeBinding binding , AST ast ) { return addImport ( binding , ast , this . defaultContext ) ; } public Type addImport ( ITypeBinding binding , AST ast , ImportRewriteContext context ) { if ( binding . isPrimitive ( ) ) { return ast . newPrimitiveType ( PrimitiveType . toCode ( binding . getName ( ) ) ) ; } ITypeBinding normalizedBinding = normalizeTypeBinding ( binding ) ; if ( normalizedBinding == null ) { return ast . newSimpleType ( ast . newSimpleName ( "invalid" ) ) ; } if ( normalizedBinding . isTypeVariable ( ) ) { return ast . newSimpleType ( ast . newSimpleName ( binding . getName ( ) ) ) ; } if ( normalizedBinding . isWildcardType ( ) ) { WildcardType wcType = ast . newWildcardType ( ) ; ITypeBinding bound = normalizedBinding . getBound ( ) ; if ( bound != null && ! bound . isWildcardType ( ) && ! bound . isCapture ( ) ) { Type boundType = addImport ( bound , ast , context ) ; wcType . setBound ( boundType , normalizedBinding . isUpperbound ( ) ) ; } return wcType ; } if ( normalizedBinding . isArray ( ) ) { Type elementType = addImport ( normalizedBinding . getElementType ( ) , ast , context ) ; return ast . newArrayType ( elementType , normalizedBinding . getDimensions ( ) ) ; } String qualifiedName = getRawQualifiedName ( normalizedBinding ) ; if ( qualifiedName . length ( ) > 0 ) { String res = internalAddImport ( qualifiedName , context ) ; ITypeBinding [ ] typeArguments = normalizedBinding . getTypeArguments ( ) ; if ( typeArguments . length > 0 ) { Type erasureType = ast . newSimpleType ( ast . newName ( res ) ) ; ParameterizedType paramType = ast . newParameterizedType ( erasureType ) ; List arguments = paramType . typeArguments ( ) ; for ( int i = 0 ; i < typeArguments . length ; i ++ ) { ITypeBinding curr = typeArguments [ i ] ; if ( containsNestedCapture ( curr , false ) ) { arguments . add ( ast . newWildcardType ( ) ) ; } else { arguments . add ( addImport ( curr , ast , context ) ) ; } } return paramType ; } return ast . newSimpleType ( ast . newName ( res ) ) ; } return ast . newSimpleType ( ast . newName ( getRawName ( normalizedBinding ) ) ) ; } public String addImport ( String qualifiedTypeName , ImportRewriteContext context ) { int angleBracketOffset = qualifiedTypeName . indexOf ( '<' ) ; if ( angleBracketOffset != - 1 ) { return internalAddImport ( qualifiedTypeName . substring ( 0 , angleBracketOffset ) , context ) + qualifiedTypeName . substring ( angleBracketOffset ) ; } int bracketOffset = qualifiedTypeName . indexOf ( '[' ) ; if ( bracketOffset != - 1 ) { return internalAddImport ( qualifiedTypeName . substring ( 0 , bracketOffset ) , context ) + qualifiedTypeName . substring ( bracketOffset ) ; } return internalAddImport ( qualifiedTypeName , context ) ; } public String addImport ( String qualifiedTypeName ) { return addImport ( qualifiedTypeName , this . defaultContext ) ; } public String addStaticImport ( IBinding binding ) { return addStaticImport ( binding , this . defaultContext ) ; } public String addStaticImport ( IBinding binding , ImportRewriteContext context ) { if ( Modifier . isStatic ( binding . getModifiers ( ) ) ) { if ( binding instanceof IVariableBinding ) { IVariableBinding variableBinding = ( IVariableBinding ) binding ; if ( variableBinding . isField ( ) ) { ITypeBinding declaringType = variableBinding . getDeclaringClass ( ) ; return addStaticImport ( getRawQualifiedName ( declaringType ) , binding . getName ( ) , true , context ) ; } } else if ( binding instanceof IMethodBinding ) { ITypeBinding declaringType = ( ( IMethodBinding ) binding ) . getDeclaringClass ( ) ; return addStaticImport ( getRawQualifiedName ( declaringType ) , binding . getName ( ) , false , context ) ; } } throw new IllegalArgumentException ( "" ) ; } public String addStaticImport ( String declaringTypeName , String simpleName , boolean isField ) { return addStaticImport ( declaringTypeName , simpleName , isField , this . defaultContext ) ; } public String addStaticImport ( String declaringTypeName , String simpleName , boolean isField , ImportRewriteContext context ) { String key = declaringTypeName + '.' + simpleName ; if ( declaringTypeName . indexOf ( '.' ) == - 1 ) { return key ; } if ( context == null ) { context = this . defaultContext ; } int kind = isField ? ImportRewriteContext . KIND_STATIC_FIELD : ImportRewriteContext . KIND_STATIC_METHOD ; this . importsKindMap . put ( key , new Integer ( kind ) ) ; int res = context . findInContext ( declaringTypeName , simpleName , kind ) ; if ( res == ImportRewriteContext . RES_NAME_CONFLICT ) { return key ; } if ( res == ImportRewriteContext . RES_NAME_UNKNOWN ) { addEntry ( STATIC_PREFIX + key ) ; } return simpleName ; } private String internalAddImport ( String fullTypeName , ImportRewriteContext context ) { int idx = fullTypeName . lastIndexOf ( '.' ) ; String typeContainerName , typeName ; if ( idx != - 1 ) { typeContainerName = fullTypeName . substring ( 0 , idx ) ; typeName = fullTypeName . substring ( idx + 1 ) ; } else { typeContainerName = "" ; typeName = fullTypeName ; } if ( typeContainerName . length ( ) == 0 && PrimitiveType . toCode ( typeName ) != null ) { return fullTypeName ; } if ( context == null ) context = this . defaultContext ; int res = context . findInContext ( typeContainerName , typeName , ImportRewriteContext . KIND_TYPE ) ; if ( res == ImportRewriteContext . RES_NAME_CONFLICT ) { return fullTypeName ; } if ( res == ImportRewriteContext . RES_NAME_UNKNOWN ) { addEntry ( NORMAL_PREFIX + fullTypeName ) ; } return typeName ; } private void addEntry ( String entry ) { this . existingImports . add ( entry ) ; if ( this . removedImports != null ) { if ( this . removedImports . remove ( entry ) ) { return ; } } if ( this . addedImports == null ) { this . addedImports = new ArrayList ( ) ; } this . addedImports . add ( entry ) ; } private boolean removeEntry ( String entry ) { if ( this . existingImports . remove ( entry ) ) { if ( this . addedImports != null ) { if ( this . addedImports . remove ( entry ) ) { return true ; } } if ( this . removedImports == null ) { this . removedImports = new ArrayList ( ) ; } this . removedImports . add ( entry ) ; return true ; } return false ; } public boolean removeImport ( String qualifiedName ) { return removeEntry ( NORMAL_PREFIX + qualifiedName ) ; } public boolean removeStaticImport ( String qualifiedName ) { return removeEntry ( STATIC_PREFIX + qualifiedName ) ; } private static String getRawName ( ITypeBinding normalizedBinding ) { return normalizedBinding . getTypeDeclaration ( ) . getName ( ) ; } private static String getRawQualifiedName ( ITypeBinding normalizedBinding ) { return normalizedBinding . getTypeDeclaration ( ) . getQualifiedName ( ) ; } public final TextEdit rewriteImports ( IProgressMonitor monitor ) throws CoreException { if ( monitor == null ) { monitor = new NullProgressMonitor ( ) ; } try { monitor . beginTask ( Messages . bind ( Messages . importRewrite_processDescription ) , 2 ) ; if ( ! hasRecordedChanges ( ) ) { this . createdImports = CharOperation . NO_STRINGS ; this . createdStaticImports = CharOperation . NO_STRINGS ; return new MultiTextEdit ( ) ; } CompilationUnit usedAstRoot = this . astRoot ; if ( usedAstRoot == null ) { ASTParser parser = ASTParser . newParser ( AST . JLS4 ) ; parser . setSource ( this . compilationUnit ) ; parser . setFocalPosition ( 0 ) ; parser . setResolveBindings ( false ) ; usedAstRoot = ( CompilationUnit ) parser . createAST ( new SubProgressMonitor ( monitor , 1 ) ) ; } ImportRewriteAnalyzer computer = new ImportRewriteAnalyzer ( this . compilationUnit , usedAstRoot , this . importOrder , this . importOnDemandThreshold , this . staticImportOnDemandThreshold , this . restoreExistingImports , this . useContextToFilterImplicitImports ) ; computer . setFilterImplicitImports ( this . filterImplicitImports ) ; if ( this . addedImports != null ) { for ( int i = 0 ; i < this . addedImports . size ( ) ; i ++ ) { String curr = ( String ) this . addedImports . get ( i ) ; computer . addImport ( curr . substring ( 1 ) , STATIC_PREFIX == curr . charAt ( 0 ) ) ; } } if ( this . removedImports != null ) { for ( int i = 0 ; i < this . removedImports . size ( ) ; i ++ ) { String curr = ( String ) this . removedImports . get ( i ) ; computer . removeImport ( curr . substring ( 1 ) , STATIC_PREFIX == curr . charAt ( 0 ) ) ; } } TextEdit result = computer . getResultingEdits ( new SubProgressMonitor ( monitor , 1 ) ) ; this . createdImports = computer . getCreatedImports ( ) ; this . createdStaticImports = computer . getCreatedStaticImports ( ) ; return result ; } finally { monitor . done ( ) ; } } public String [ ] getCreatedImports ( ) { return this . createdImports ; } public String [ ] getCreatedStaticImports ( ) { return this . createdStaticImports ; } public String [ ] getAddedImports ( ) { return filterFromList ( this . addedImports , NORMAL_PREFIX ) ; } public String [ ] getAddedStaticImports ( ) { return filterFromList ( this . addedImports , STATIC_PREFIX ) ; } public String [ ] getRemovedImports ( ) { return filterFromList ( this . removedImports , NORMAL_PREFIX ) ; } public String [ ] getRemovedStaticImports ( ) { return filterFromList ( this . removedImports , STATIC_PREFIX ) ; } public boolean hasRecordedChanges ( ) { return ! this . restoreExistingImports || ( this . addedImports != null && ! this . addedImports . isEmpty ( ) ) || ( this . removedImports != null && ! this . removedImports . isEmpty ( ) ) ; } private static String [ ] filterFromList ( List imports , char prefix ) { if ( imports == null ) { return CharOperation . NO_STRINGS ; } ArrayList res = new ArrayList ( ) ; for ( int i = 0 ; i < imports . size ( ) ; i ++ ) { String curr = ( String ) imports . get ( i ) ; if ( prefix == curr . charAt ( 0 ) ) { res . add ( curr . substring ( 1 ) ) ; } } return ( String [ ] ) res . toArray ( new String [ res . size ( ) ] ) ; } } </s>