| /******************************************************************************* |
| * Copyright (c) 2017, 2018 GK Software SE, and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Stephan Herrmann - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.ui.wizards.buildpaths; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.stream.Collectors; |
| |
| import org.eclipse.core.runtime.IPath; |
| |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| |
| import org.eclipse.jdt.core.IClasspathEntry; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| |
| /** |
| * Node in the tree of CPListElement et al, representing a module directive like add-exports ... |
| */ |
| public abstract class ModuleEncapsulationDetail { |
| |
| protected CPListElementAttribute fAttribElem; |
| |
| public CPListElementAttribute getParent() { |
| return fAttribElem; |
| } |
| |
| /** |
| * Retrieve the java element(s) targeted by a given classpath entry. |
| * @param currentProject the Java project holding the classpath entry |
| * @param path the path value of the classpath entry |
| * @return either an array of {@link IPackageFragmentRoot} or a singleton array of {@link IJavaProject} |
| * targeted by the given classpath entry, or {@code null} if no not found |
| */ |
| public static IJavaElement[] getTargetJavaElements(IJavaProject currentProject, IPath path) { |
| IResource member= ResourcesPlugin.getWorkspace().getRoot().findMember(path); |
| if (member != null) { |
| IJavaElement element= JavaCore.create(member); |
| if (element != null) |
| return new IJavaElement[] {element}; |
| } else if (path != null && path.isAbsolute()) { |
| try { |
| for (IClasspathEntry classpathEntry : currentProject.getRawClasspath()) { |
| if (classpathEntry.getPath().equals(path)) { |
| switch (classpathEntry.getEntryKind()) { |
| case IClasspathEntry.CPE_LIBRARY: |
| return new IJavaElement[] {currentProject.getPackageFragmentRoot(path.toString())}; |
| default: |
| // keep looking |
| } |
| } |
| } |
| } catch (JavaModelException e) { |
| JavaPlugin.log(e); |
| } |
| } else { |
| try { |
| for (IClasspathEntry classpathEntry : currentProject.getRawClasspath()) { |
| if (classpathEntry.getPath().equals(path)) { |
| return currentProject.findUnfilteredPackageFragmentRoots(classpathEntry); |
| } |
| } |
| } catch (JavaModelException e) { |
| JavaPlugin.log(e); |
| } |
| } |
| return null; |
| } |
| |
| public static String encodeFiltered(ModuleEncapsulationDetail[] details, Class<?> detailClass) { |
| return Arrays.stream(details) |
| .filter(detailClass::isInstance) |
| .map(ModuleEncapsulationDetail::toString) |
| .collect(Collectors.joining(":")); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Node in the tree of CPListElement et al, representing a patch-module directive. |
| */ |
| static class ModulePatch extends ModuleEncapsulationDetail { |
| |
| public static ModulePatch fromString(CPListElementAttribute attribElem, String value) { |
| return new ModulePatch(value, attribElem); |
| } |
| |
| public final String fModule; |
| |
| public ModulePatch(String module, CPListElementAttribute attribElem) { |
| fModule= module; |
| fAttribElem= attribElem; |
| } |
| |
| @Override |
| public String toString() { |
| return fModule; |
| } |
| } |
| |
| /** |
| * Node in the tree of CPListElement et al, representing an add-exports module directive. |
| */ |
| static class ModuleAddExport extends ModuleEncapsulationDetail { |
| |
| public static ModuleAddExport fromString(CPListElementAttribute attribElem, String value) { |
| int slash= value.indexOf('/'); |
| int equals= value.indexOf('='); |
| if (slash != -1 && equals != -1 && equals > slash) { |
| return new ModuleAddExport(value.substring(0, slash), |
| value.substring(slash+1, equals), |
| value.substring(equals+1), |
| attribElem); |
| } |
| return null; |
| } |
| |
| public static Collection<ModuleAddExport> fromMultiString(CPListElementAttribute attribElem, String values) { |
| List<ModuleAddExport> exports= new ArrayList<>(); |
| for (String value : values.split(":")) { //$NON-NLS-1$ |
| ModuleAddExport export= fromString(attribElem, value); |
| if (export != null) |
| exports.add(export); |
| } |
| return exports; |
| } |
| |
| public final String fSourceModule; |
| public final String fPackage; |
| public final String fTargetModules; |
| |
| public ModuleAddExport(String sourceModule, String aPackage, String targetModules, CPListElementAttribute attribElem) { |
| fSourceModule= sourceModule; |
| fPackage= aPackage; |
| fTargetModules= targetModules; |
| fAttribElem= attribElem; |
| } |
| |
| @Override |
| public String toString() { |
| return fSourceModule+'/'+fPackage+'='+fTargetModules; |
| } |
| } |
| |
| /** |
| * Node in the tree of CPListElement et al, representing an add-reads module directive. |
| */ |
| static class ModuleAddReads extends ModuleEncapsulationDetail { |
| |
| public static ModuleAddReads fromString(CPListElementAttribute attribElem, String value) { |
| int equals= value.indexOf('='); |
| if (equals != -1) { |
| return new ModuleAddReads(value.substring(0, equals), |
| value.substring(equals+1), |
| attribElem); |
| } |
| return null; |
| } |
| |
| public static Collection<ModuleAddReads> fromMultiString(CPListElementAttribute attribElem, String values) { |
| List<ModuleAddReads> readss= new ArrayList<>(); |
| for (String value : values.split(":")) { //$NON-NLS-1$ |
| ModuleAddReads reads= fromString(attribElem, value); |
| if (reads != null) |
| readss.add(reads); |
| } |
| return readss; |
| } |
| |
| public final String fSourceModule; |
| public final String fTargetModule; |
| |
| public ModuleAddReads(String sourceModule, String targetModule, CPListElementAttribute attribElem) { |
| fSourceModule= sourceModule; |
| fTargetModule= targetModule; |
| fAttribElem= attribElem; |
| } |
| |
| @Override |
| public String toString() { |
| return fSourceModule+'='+fTargetModule; |
| } |
| } |
| |
| /** |
| * Node in the tree of CPListElement et al, representing a limit-modules directive. |
| */ |
| static class LimitModules extends ModuleEncapsulationDetail { |
| |
| public static LimitModules fromString(CPListElementAttribute attribElem, String value) { |
| String[] modules= value.split(","); //$NON-NLS-1$ |
| for (int i= 0; i < modules.length; i++) { |
| modules[i]= modules[i].trim(); |
| } |
| return new LimitModules(Arrays.asList(modules), attribElem); |
| } |
| |
| public final List<String> fExplicitlyIncludedModules; |
| |
| public LimitModules(List<String> explicitlyIncludedModules, CPListElementAttribute attribElem) { |
| fExplicitlyIncludedModules= explicitlyIncludedModules; |
| fAttribElem= attribElem; |
| } |
| @Override |
| public String toString() { |
| return String.join(",", fExplicitlyIncludedModules); //$NON-NLS-1$ |
| } |
| } |
| } |