]> git.uio.no Git - ifi-stolz-refaktor.git/blobdiff - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/text/correction/ReorgCorrectionsSubProcessor.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / text / correction / ReorgCorrectionsSubProcessor.java
diff --git a/case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/text/correction/ReorgCorrectionsSubProcessor.java b/case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/text/correction/ReorgCorrectionsSubProcessor.java
new file mode 100644 (file)
index 0000000..aeab5b5
--- /dev/null
@@ -0,0 +1,698 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012 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
+ *     Matt Chapman, mpchapman@gmail.com - 89977 Make JDT .java agnostic
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.ui.text.correction;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+
+import org.eclipse.text.edits.TextEdit;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableContext;
+
+import org.eclipse.jface.text.IDocument;
+
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.progress.IProgressService;
+
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+
+import org.eclipse.jdt.core.ClasspathContainerInitializer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageDeclaration;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jdt.core.dom.ImportDeclaration;
+import org.eclipse.jdt.core.dom.Modifier;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.QualifiedName;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.dom.Type;
+
+import org.eclipse.jdt.internal.corext.codemanipulation.AddImportsOperation;
+import org.eclipse.jdt.internal.corext.codemanipulation.AddImportsOperation.IChooseImportQuery;
+import org.eclipse.jdt.internal.corext.dom.ASTNodes;
+import org.eclipse.jdt.internal.corext.fix.CleanUpConstants;
+import org.eclipse.jdt.internal.corext.fix.IProposableFix;
+import org.eclipse.jdt.internal.corext.fix.UnusedCodeFix;
+import org.eclipse.jdt.internal.corext.refactoring.changes.CreatePackageChange;
+import org.eclipse.jdt.internal.corext.refactoring.changes.MoveCompilationUnitChange;
+import org.eclipse.jdt.internal.corext.refactoring.changes.RenameCompilationUnitChange;
+import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
+import org.eclipse.jdt.internal.corext.util.Messages;
+
+import org.eclipse.jdt.launching.IVMInstall;
+import org.eclipse.jdt.launching.IVMInstall2;
+import org.eclipse.jdt.launching.IVMInstallType;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
+import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
+
+import org.eclipse.jdt.ui.JavaElementLabels;
+import org.eclipse.jdt.ui.actions.OrganizeImportsAction;
+import org.eclipse.jdt.ui.cleanup.CleanUpOptions;
+import org.eclipse.jdt.ui.text.java.IInvocationContext;
+import org.eclipse.jdt.ui.text.java.IProblemLocation;
+import org.eclipse.jdt.ui.text.java.correction.CUCorrectionProposal;
+import org.eclipse.jdt.ui.text.java.correction.ChangeCorrectionProposal;
+import org.eclipse.jdt.ui.text.java.correction.ICommandAccess;
+
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.JavaPluginImages;
+import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
+import org.eclipse.jdt.internal.ui.fix.UnusedCodeCleanUp;
+import org.eclipse.jdt.internal.ui.javaeditor.AddImportOnSelectionAction;
+import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
+import org.eclipse.jdt.internal.ui.preferences.BuildPathsPropertyPage;
+import org.eclipse.jdt.internal.ui.text.correction.proposals.CorrectMainTypeNameProposal;
+import org.eclipse.jdt.internal.ui.text.correction.proposals.CorrectPackageDeclarationProposal;
+import org.eclipse.jdt.internal.ui.text.correction.proposals.FixCorrectionProposal;
+import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
+import org.eclipse.jdt.internal.ui.util.CoreUtility;
+import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ClasspathFixSelectionDialog;
+
+public class ReorgCorrectionsSubProcessor {
+
+       public static void getWrongTypeNameProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
+               ICompilationUnit cu= context.getCompilationUnit();
+               boolean isLinked= cu.getResource().isLinked();
+
+               IJavaProject javaProject= cu.getJavaProject();
+               String sourceLevel= javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
+               String compliance= javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+
+               CompilationUnit root= context.getASTRoot();
+
+               ASTNode coveredNode= problem.getCoveredNode(root);
+               if (!(coveredNode instanceof SimpleName))
+                       return;
+
+               ASTNode parentType= coveredNode.getParent();
+               if (!(parentType instanceof AbstractTypeDeclaration))
+                       return;
+
+               String currTypeName= ((SimpleName) coveredNode).getIdentifier();
+               String newTypeName= JavaCore.removeJavaLikeExtension(cu.getElementName());
+
+               boolean hasOtherPublicTypeBefore= false;
+
+               boolean found= false;
+               List<AbstractTypeDeclaration> types= root.types();
+               for (int i= 0; i < types.size(); i++) {
+                       AbstractTypeDeclaration curr= types.get(i);
+                       if (parentType != curr) {
+                               if (newTypeName.equals(curr.getName().getIdentifier())) {
+                                       return;
+                               }
+                               if (!found && Modifier.isPublic(curr.getModifiers())) {
+                                       hasOtherPublicTypeBefore= true;
+                               }
+                       } else {
+                               found= true;
+                       }
+               }
+               if (!JavaConventions.validateJavaTypeName(newTypeName, sourceLevel, compliance).matches(IStatus.ERROR)) {
+                       proposals.add(new CorrectMainTypeNameProposal(cu, context, currTypeName, newTypeName, 5));
+               }
+
+               if (!hasOtherPublicTypeBefore) {
+                       String newCUName= JavaModelUtil.getRenamedCUName(cu, currTypeName);
+                       ICompilationUnit newCU= ((IPackageFragment) (cu.getParent())).getCompilationUnit(newCUName);
+                       if (!newCU.exists() && !isLinked && !JavaConventions.validateCompilationUnitName(newCUName, sourceLevel, compliance).matches(IStatus.ERROR)) {
+                               RenameCompilationUnitChange change= new RenameCompilationUnitChange(cu, newCUName);
+
+                               // rename CU
+                               String label= Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_renamecu_description, BasicElementLabels.getResourceName(newCUName));
+                               proposals.add(new ChangeCorrectionProposal(label, change, 6, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_RENAME)));
+                       }
+               }
+       }
+
+       public static void getWrongPackageDeclNameProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
+               ICompilationUnit cu= context.getCompilationUnit();
+               boolean isLinked= cu.getResource().isLinked();
+
+               // correct package declaration
+               int relevance= cu.getPackageDeclarations().length == 0 ? 7 : 5; // bug 38357
+               proposals.add(new CorrectPackageDeclarationProposal(cu, problem, relevance));
+
+               // move to package
+               IPackageDeclaration[] packDecls= cu.getPackageDeclarations();
+               String newPackName= packDecls.length > 0 ? packDecls[0].getElementName() : ""; //$NON-NLS-1$
+
+               IPackageFragmentRoot root= JavaModelUtil.getPackageFragmentRoot(cu);
+               IPackageFragment newPack= root.getPackageFragment(newPackName);
+
+               ICompilationUnit newCU= newPack.getCompilationUnit(cu.getElementName());
+               if (!newCU.exists() && !isLinked) {
+                       String label;
+                       if (newPack.isDefaultPackage()) {
+                               label= Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_movecu_default_description, BasicElementLabels.getFileName(cu));
+                       } else {
+                               String packageLabel= JavaElementLabels.getElementLabel(newPack, JavaElementLabels.ALL_DEFAULT);
+                               label= Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_movecu_description, new Object[] { BasicElementLabels.getFileName(cu), packageLabel });
+                       }
+                       CompositeChange composite= new CompositeChange(label);
+                       composite.add(new CreatePackageChange(newPack));
+                       composite.add(new MoveCompilationUnitChange(cu, newPack));
+
+                       proposals.add(new ChangeCorrectionProposal(label, composite, 6, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_MOVE)));
+               }
+       }
+
+       public static void removeImportStatementProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
+               IProposableFix fix= UnusedCodeFix.createRemoveUnusedImportFix(context.getASTRoot(), problem);
+               if (fix != null) {
+                       Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_DELETE_IMPORT);
+                       Map<String, String> options= new Hashtable<String, String>();
+                       options.put(CleanUpConstants.REMOVE_UNUSED_CODE_IMPORTS, CleanUpOptions.TRUE);
+                       FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new UnusedCodeCleanUp(options), 6, image, context);
+                       proposals.add(proposal);
+               }
+
+               final ICompilationUnit cu= context.getCompilationUnit();
+               String name= CorrectionMessages.ReorgCorrectionsSubProcessor_organizeimports_description;
+               ChangeCorrectionProposal proposal= new ChangeCorrectionProposal(name, null, 5, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE)) {
+                       @Override
+                       public void apply(IDocument document) {
+                               IEditorInput input= new FileEditorInput((IFile) cu.getResource());
+                               IWorkbenchPage p= JavaPlugin.getActivePage();
+                               if (p == null) {
+                                       return;
+                               }
+                               IEditorPart part= p.findEditor(input);
+                               if (part instanceof JavaEditor) {
+                                       OrganizeImportsAction action= new OrganizeImportsAction((JavaEditor) part);
+                                       action.run(cu);
+                               }
+                       }
+               };
+               proposals.add(proposal);
+       }
+
+       public static class ClasspathFixCorrectionProposal extends CUCorrectionProposal {
+
+               private final int fOffset;
+               private final int fLength;
+               private final String fMissingType;
+
+               private TextEdit fResultingEdit;
+
+               public ClasspathFixCorrectionProposal(ICompilationUnit cu, int offset, int length, String missingType) {
+                       super(CorrectionMessages.ReorgCorrectionsSubProcessor_project_seup_fix_description, cu, -10, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE));
+                       fOffset= offset;
+                       fLength= length;
+                       fMissingType= missingType;
+               }
+
+               @Override
+               public void apply(IDocument document) {
+                       IRunnableContext context= JavaPlugin.getActiveWorkbenchWindow();
+                       if (context == null) {
+                               context= new BusyIndicatorRunnableContext();
+                       }
+                       Shell shell= JavaPlugin.getActiveWorkbenchShell();
+                       if (ClasspathFixSelectionDialog.openClasspathFixSelectionDialog(shell, getCompilationUnit().getJavaProject(), fMissingType, context)) {
+                               if (fMissingType.indexOf('.') == -1) {
+                                       try {
+                                               IChooseImportQuery query= AddImportOnSelectionAction.newDialogQuery(shell);
+                                               AddImportsOperation op= new AddImportsOperation(getCompilationUnit(), fOffset, fLength, query, false, false);
+                                               IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
+                                               progressService.runInUI(context, new WorkbenchRunnableAdapter(op, op.getScheduleRule()), op.getScheduleRule());
+                                               fResultingEdit= op.getResultingEdit();
+                                               super.apply(document);
+                                       } catch (InvocationTargetException e) {
+                                               JavaPlugin.log(e);
+                                       } catch (InterruptedException e) {
+                                               // ignore
+                                       }
+                               }
+                       }
+               }
+
+               @Override
+               protected void addEdits(IDocument document, TextEdit editRoot) throws CoreException {
+                       if (fResultingEdit != null) {
+                               editRoot.addChild(fResultingEdit);
+                       }
+               }
+
+               @Override
+               public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
+                       return Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_project_seup_fix_info, BasicElementLabels.getJavaElementName(fMissingType));
+               }
+       }
+
+       public static void addProjectSetupFixProposal(IInvocationContext context, IProblemLocation problem, String missingType, Collection<ICommandAccess> proposals) {
+               proposals.add(new ClasspathFixCorrectionProposal(context.getCompilationUnit(), problem.getOffset(), problem.getLength(), missingType));
+       }
+
+
+       public static void importNotFoundProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) throws CoreException {
+               ICompilationUnit cu= context.getCompilationUnit();
+
+               ASTNode selectedNode= problem.getCoveringNode(context.getASTRoot());
+               if (selectedNode == null) {
+                       return;
+               }
+               ImportDeclaration importDeclaration= (ImportDeclaration) ASTNodes.getParent(selectedNode, ASTNode.IMPORT_DECLARATION);
+               if (importDeclaration == null) {
+                       return;
+               }
+               if (!importDeclaration.isOnDemand()) {
+                       Name name= importDeclaration.getName();
+                       if (importDeclaration.isStatic() && name.isQualifiedName()) {
+                               name= ((QualifiedName) name).getQualifier();
+                       }
+                       int kind= JavaModelUtil.is50OrHigher(cu.getJavaProject()) ? SimilarElementsRequestor.REF_TYPES : SimilarElementsRequestor.CLASSES | SimilarElementsRequestor.INTERFACES;
+                       UnresolvedElementsSubProcessor.addNewTypeProposals(cu, name, kind, 5, proposals);
+               }
+
+               String name= ASTNodes.asString(importDeclaration.getName());
+               if (importDeclaration.isOnDemand()) {
+                       name= JavaModelUtil.concatenateName(name, "*"); //$NON-NLS-1$
+               }
+               addProjectSetupFixProposal(context, problem, name, proposals);
+       }
+
+       private static final class OpenBuildPathCorrectionProposal extends ChangeCorrectionProposal {
+               private final IProject fProject;
+               private final IBinding fReferencedType;
+               private OpenBuildPathCorrectionProposal(IProject project, String label, int relevance, IBinding referencedType) {
+                       super(label, null, relevance, null);
+                       fProject= project;
+                       fReferencedType= referencedType;
+                       setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_ACCESSRULES_ATTRIB));
+               }
+               @Override
+               public void apply(IDocument document) {
+                       Map<Object, Object> data= null;
+                       if (fReferencedType != null) {
+                               IJavaElement elem= fReferencedType.getJavaElement();
+                               if (elem != null) {
+                                       IPackageFragmentRoot root= (IPackageFragmentRoot) elem.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+                                       if (root != null) {
+                                               try {
+                                                       IClasspathEntry entry= root.getRawClasspathEntry();
+                                                       if (entry != null) {
+                                                               data= new HashMap<Object, Object>(1);
+                                                               data.put(BuildPathsPropertyPage.DATA_REVEAL_ENTRY, entry);
+                                                               if (entry.getEntryKind() != IClasspathEntry.CPE_CONTAINER) {
+                                                                       data.put(BuildPathsPropertyPage.DATA_REVEAL_ATTRIBUTE_KEY, CPListElement.ACCESSRULES);
+                                                               }
+                                                       }
+                                               } catch (JavaModelException e) {
+                                                       // ignore
+                                               }
+                                       }
+                               }
+                       }
+                       PreferencesUtil.createPropertyDialogOn(JavaPlugin.getActiveWorkbenchShell(), fProject, BuildPathsPropertyPage.PROP_ID, null, data).open();
+               }
+               /*
+                * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension5#getAdditionalProposalInfo(org.eclipse.core.runtime.IProgressMonitor)
+                * @since 3.5
+                */
+               @Override
+               public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
+                       return Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_configure_buildpath_description, BasicElementLabels.getResourceName(fProject));
+               }
+       }
+
+       private static final class ChangeToRequiredCompilerCompliance extends ChangeCorrectionProposal implements IWorkspaceRunnable {
+
+               private final IJavaProject fProject;
+               private final boolean fChangeOnWorkspace;
+               private final String fRequiredVersion;
+
+               private Job fUpdateJob;
+               private boolean fRequiredJREFound;
+
+               public ChangeToRequiredCompilerCompliance(String name, IJavaProject project, boolean changeOnWorkspace, String requiredVersion, int relevance) {
+                       super(name, null, relevance, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE));
+                       fProject= project;
+                       fChangeOnWorkspace= changeOnWorkspace;
+                       fRequiredVersion= requiredVersion;
+                       fUpdateJob= null;
+                       fRequiredJREFound= false;
+               }
+
+               private boolean isRequiredOrGreaterVMInstall(IVMInstall install) {
+                       if (install instanceof IVMInstall2) {
+                               String compliance= JavaModelUtil.getCompilerCompliance((IVMInstall2) install, JavaCore.VERSION_1_3);
+                               return !JavaModelUtil.isVersionLessThan(compliance, fRequiredVersion);
+                       }
+                       return false;
+               }
+
+               private String getVMInstallCompliance(IVMInstall install) {
+                       if (install instanceof IVMInstall2) {
+                               String compliance= JavaModelUtil.getCompilerCompliance((IVMInstall2) install, JavaCore.VERSION_1_3);
+                               return compliance;
+                       }
+                       return JavaCore.VERSION_1_1;
+               }
+               
+               private IVMInstall findRequiredOrGreaterVMInstall() {
+                       String bestMatchingCompliance= null;
+                       IVMInstall bestMatchingVMInstall= null;
+                       IVMInstallType[] installTypes= JavaRuntime.getVMInstallTypes();
+                       for (int i= 0; i < installTypes.length; i++) {
+                               IVMInstall[] installs= installTypes[i].getVMInstalls();
+                               for (int k= 0; k < installs.length; k++) {
+                                       String vmInstallCompliance= getVMInstallCompliance(installs[k]);
+                                       
+                                       if (fRequiredVersion.equals(vmInstallCompliance)) {
+                                               return installs[k]; // perfect match
+                                               
+                                       } else if (JavaModelUtil.isVersionLessThan(vmInstallCompliance, fRequiredVersion)) {
+                                               continue; // no match
+                                               
+                                       } else if (bestMatchingVMInstall != null) {
+                                               if (JavaModelUtil.isVersionLessThan(bestMatchingCompliance, vmInstallCompliance)) {
+                                                       continue; // the other one is the least matching
+                                               }
+                                       }
+                                       bestMatchingCompliance= vmInstallCompliance;
+                                       bestMatchingVMInstall= installs[k];
+                               }
+                       }
+                       return null;
+               }
+
+               public void run(IProgressMonitor monitor) throws CoreException {
+                       boolean needsBuild= updateJRE(monitor);
+                       if (needsBuild) {
+                               fUpdateJob= CoreUtility.getBuildJob(fChangeOnWorkspace ? null : fProject.getProject());
+                       }
+               }
+
+               private boolean updateJRE( IProgressMonitor monitor) throws CoreException, JavaModelException {
+                       // Caveat: Returns true iff the classpath has not been changed.
+                       // If the classpath is changed, JDT Core triggers a build for free.
+                       // If the classpath is not changed, we have to trigger a build because we changed
+                       // the compiler compliance in #apply(IDocument).
+                       try {
+                               if (fChangeOnWorkspace) {
+                                       IVMInstall vmInstall= findRequiredOrGreaterVMInstall();
+                                       fRequiredJREFound= vmInstall != null;
+                                       if (vmInstall != null) {
+                                               IVMInstall install= JavaRuntime.getVMInstall(fProject); // can be null
+                                               monitor.beginTask(CorrectionMessages.ReorgCorrectionsSubProcessor_50_compliance_operation, 4);
+                                               IVMInstall defaultVM= JavaRuntime.getDefaultVMInstall(); // can be null
+                                               if (defaultVM != null && !defaultVM.equals(install)) {
+                                                       IPath newPath= new Path(JavaRuntime.JRE_CONTAINER);
+                                                       updateClasspath(newPath, new SubProgressMonitor(monitor, 1));
+                                               } else {
+                                                       monitor.worked(1);
+                                               }
+                                               if (defaultVM == null || !isRequiredOrGreaterVMInstall(defaultVM)) {
+                                                       JavaRuntime.setDefaultVMInstall(vmInstall, new SubProgressMonitor(monitor, 3), true);
+                                                       return false;
+                                               }
+                                               return true;
+                                       }
+
+                               } else {
+                                       IExecutionEnvironment bestEE= findBestMatchingEE();
+                                       fRequiredJREFound= bestEE != null;
+                                       if (bestEE != null) {
+                                               IPath newPath= JavaRuntime.newJREContainerPath(bestEE);
+                                               boolean classpathUpdated= updateClasspath(newPath, monitor);
+                                               return !classpathUpdated;
+                                       }
+                               }
+                       } finally {
+                               monitor.done();
+                       }
+                       return true;
+               }
+
+               private IExecutionEnvironment findBestMatchingEE() {
+                       IExecutionEnvironmentsManager eeManager= JavaRuntime.getExecutionEnvironmentsManager();
+                       IExecutionEnvironment[] ees= eeManager.getExecutionEnvironments();
+                       IExecutionEnvironment bestEE= null;
+                       String bestEECompliance= null;
+                       
+                       for (int i= 0; i < ees.length; i++) {
+                               IExecutionEnvironment ee= ees[i];
+                               String eeCompliance= JavaModelUtil.getExecutionEnvironmentCompliance(ee);
+                               String eeId= ee.getId();
+                               
+                               if (fRequiredVersion.equals(eeCompliance)) {
+                                       if (eeId.startsWith("J") && eeId.endsWith(fRequiredVersion)) { //$NON-NLS-1$
+                                               bestEE= ee;
+                                               break; // perfect match
+                                       }
+                                       
+                               } else if (JavaModelUtil.isVersionLessThan(eeCompliance, fRequiredVersion)) {
+                                       continue; // no match
+                                       
+                               } else { // possible match
+                                       if (bestEE != null) {
+                                               if (! eeId.startsWith("J")) { //$NON-NLS-1$
+                                                       continue; // avoid taking e.g. OSGi profile if a Java profile is available
+                                               }
+                                               if (JavaModelUtil.isVersionLessThan(bestEECompliance, eeCompliance)) {
+                                                       continue; // the other one is the least matching
+                                               }
+                                       }
+                               }
+                               // found a new best
+                               bestEE= ee;
+                               bestEECompliance= eeCompliance;
+                       }
+                       return bestEE;
+               }
+
+               private boolean updateClasspath(IPath newPath, IProgressMonitor monitor) throws JavaModelException {
+                       boolean updated= false;
+                       
+                       IClasspathEntry[] classpath= fProject.getRawClasspath();
+                       IPath jreContainerPath= new Path(JavaRuntime.JRE_CONTAINER);
+                       for (int i= 0; i < classpath.length; i++) {
+                               IClasspathEntry curr= classpath[i];
+                               if (curr.getEntryKind() == IClasspathEntry.CPE_CONTAINER && curr.getPath().matchingFirstSegments(jreContainerPath) > 0) {
+                                       if (! newPath.equals(curr.getPath())) {
+                                               updated= true;
+                                               classpath[i]= JavaCore.newContainerEntry(newPath, curr.getAccessRules(), curr.getExtraAttributes(), curr.isExported());
+                                       }
+                               }
+                       }
+                       if (updated) {
+                               fProject.setRawClasspath(classpath, monitor);
+                       }
+                       return updated;
+               }
+
+               /* (non-Javadoc)
+                * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+                */
+               @Override
+               public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
+                       StringBuffer message= new StringBuffer();
+                       if (fChangeOnWorkspace) {
+                               message.append(Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_required_compliance_changeworkspace_description, fRequiredVersion));
+                       } else {
+                               message.append(Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_required_compliance_changeproject_description, fRequiredVersion));
+                       }
+
+                       try {
+                               IVMInstall install= JavaRuntime.getVMInstall(fProject); // can be null
+                               if (fChangeOnWorkspace) {
+                                       IVMInstall vmInstall= findRequiredOrGreaterVMInstall();
+                                       if (vmInstall != null) {
+                                               IVMInstall defaultVM= JavaRuntime.getDefaultVMInstall(); // can be null
+                                               if (defaultVM != null && !defaultVM.equals(install)) {
+                                                       message.append(CorrectionMessages.ReorgCorrectionsSubProcessor_50_compliance_changeProjectJREToDefault_description);
+                                               }
+                                               if (defaultVM == null || !isRequiredOrGreaterVMInstall(defaultVM)) {
+                                                       message.append(Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_50_compliance_changeWorkspaceJRE_description, vmInstall.getName()));
+                                               }
+                                       }
+                               } else {
+                                       IExecutionEnvironment bestEE= findBestMatchingEE();
+                                       if (bestEE != null) {
+                                               if (install == null || !isEEOnClasspath(bestEE)) {
+                                                       message.append(Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_50_compliance_changeProjectJRE_description, bestEE.getId()));
+                                               }
+                                       }
+                               }
+                       } catch (CoreException e) {
+                               // ignore
+                       }
+                       return message.toString();
+               }
+
+               private boolean isEEOnClasspath(IExecutionEnvironment ee) throws JavaModelException {
+                       IPath eePath= JavaRuntime.newJREContainerPath(ee);
+                       
+                       for (IClasspathEntry entry: fProject.getRawClasspath()) {
+                               if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER && entry.getPath().equals(eePath))
+                                       return true;
+                       }
+                       return false;
+               }
+
+               /* (non-Javadoc)
+                * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(IDocument)
+                */
+               @Override
+               public void apply(IDocument document) {
+                       if (fChangeOnWorkspace) {
+                               Hashtable<String, String> map= JavaCore.getOptions();
+                               JavaModelUtil.setComplianceOptions(map, fRequiredVersion);
+                               JavaCore.setOptions(map);
+                       } else {
+                               Map<String, String> map= fProject.getOptions(false);
+                               int optionsCount= map.size();
+                               JavaModelUtil.setComplianceOptions(map, fRequiredVersion);
+                               if (map.size() > optionsCount) {
+                                       // options have been added -> ensure that all compliance options from preference page set
+                                       JavaModelUtil.setDefaultClassfileOptions(map, fRequiredVersion);
+                               }
+                               fProject.setOptions(map);
+                       }
+                       try {
+                               IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
+                               progressService.run(true, true, new WorkbenchRunnableAdapter(this));
+                       } catch (InvocationTargetException e) {
+                               JavaPlugin.log(e);
+                       } catch (InterruptedException e) {
+                               return;
+                       }
+
+                       if (fUpdateJob != null) {
+                               fUpdateJob.schedule();
+                       }
+
+                       if (!fRequiredJREFound) {
+                               MessageDialog.openInformation(JavaPlugin.getActiveWorkbenchShell(),
+                                               Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_no_required_jre_title, fRequiredVersion),
+                                               Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_no_required_jre_message, fRequiredVersion));
+                       }
+               }
+       }
+
+       /**
+        * Adds a proposal to increase the compiler compliance level
+        * @param context the context
+        * @param problem the current problem
+        * @param proposals the resulting proposals
+        * @param requiredVersion the minimal required Java compiler version
+        */
+       public static void getNeedHigherComplianceProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals, String requiredVersion) {
+               IJavaProject project= context.getCompilationUnit().getJavaProject();
+
+               String label1= Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_change_project_compliance_description, requiredVersion);
+               proposals.add(new ChangeToRequiredCompilerCompliance(label1, project, false, requiredVersion, 5));
+
+               if (project.getOption(JavaCore.COMPILER_COMPLIANCE, false) == null) {
+                       String label2= Messages.format(CorrectionMessages.ReorgCorrectionsSubProcessor_change_workspace_compliance_description, requiredVersion);
+                       proposals.add(new ChangeToRequiredCompilerCompliance(label2, project, true, requiredVersion, 6));
+               }
+       }
+
+       /**
+        * Adds a proposal that opens the build path dialog
+        * @param context the context
+        * @param problem the current problem
+        * @param proposals the resulting proposals
+        */
+       public static void getIncorrectBuildPathProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
+               IProject project= context.getCompilationUnit().getJavaProject().getProject();
+               String label= CorrectionMessages.ReorgCorrectionsSubProcessor_configure_buildpath_label;
+               OpenBuildPathCorrectionProposal proposal= new OpenBuildPathCorrectionProposal(project, label, 5, null);
+               proposals.add(proposal);
+       }
+
+       public static void getAccessRulesProposals(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
+               IBinding referencedElement= null;
+               ASTNode node= problem.getCoveredNode(context.getASTRoot());
+               if (node instanceof Type) {
+                       referencedElement= ((Type) node).resolveBinding();
+               } else if (node instanceof Name) {
+                       referencedElement= ((Name) node).resolveBinding();
+               }
+               if (referencedElement != null && canModifyAccessRules(referencedElement)) {
+                       IProject project= context.getCompilationUnit().getJavaProject().getProject();
+                       String label= CorrectionMessages.ReorgCorrectionsSubProcessor_accessrules_description;
+                       OpenBuildPathCorrectionProposal proposal= new OpenBuildPathCorrectionProposal(project, label, 5, referencedElement);
+                       proposals.add(proposal);
+               }
+       }
+
+       private static boolean canModifyAccessRules(IBinding binding) {
+               IJavaElement element= binding.getJavaElement();
+               if (element == null)
+                       return false;
+
+               IPackageFragmentRoot root= JavaModelUtil.getPackageFragmentRoot(element);
+               if (root == null)
+                       return false;
+
+               try {
+                       IClasspathEntry classpathEntry= root.getRawClasspathEntry();
+                       if (classpathEntry == null)
+                               return false;
+                       if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY)
+                               return true;
+                       if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
+                               ClasspathContainerInitializer classpathContainerInitializer= JavaCore.getClasspathContainerInitializer(classpathEntry.getPath().segment(0));
+                               IStatus status= classpathContainerInitializer.getAccessRulesStatus(classpathEntry.getPath(), root.getJavaProject());
+                               return status.isOK();
+                       }
+               } catch (JavaModelException e) {
+                       return false;
+               }
+               return false;
+       }
+
+
+}