| /*=============================================================================# |
| # Copyright (c) 2000, 2020 IBM Corporation and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 |
| # |
| # Contributors: |
| # IBM Corporation - org.eclipse.jdt: initial API and implementation |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.ltk.buildpath.core; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; |
| |
| import java.util.Objects; |
| |
| import org.eclipse.core.runtime.IPath; |
| |
| import org.eclipse.statet.jcommons.collections.ImCollections; |
| import org.eclipse.statet.jcommons.collections.ImList; |
| import org.eclipse.statet.jcommons.lang.NonNull; |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| import org.eclipse.statet.jcommons.lang.ObjectUtils; |
| |
| |
| @NonNullByDefault |
| public class BasicBuildpathElement implements BuildpathElement { |
| |
| |
| private static final ImList<String> UNINITIALIZED_PATTERNS= ImCollections.newList("UNINITIALIZED_PATTERNS"); //$NON-NLS-1$ |
| |
| |
| private final BuildpathElementType type; |
| |
| /** |
| * The meaning of the path of a classpath entry depends on its entry kind:<ul> |
| * <li>Source code in the current project (<code>SOURCE</code>) - |
| * The path associated with this entry is the absolute path to the root folder. </li> |
| * <li>A binary library in the current project (<code>LIBRARY</code>) - the path |
| * associated with this entry is the absolute path to the JAR (or root folder), and |
| * in case it refers to an external JAR, then there is no associated resource in |
| * the workbench. |
| * <li>A required project (<code>PROJECT</code>) - the path of the entry denotes the |
| * path to the corresponding project resource.</li> |
| * <li>A variable entry (<code>VARIABLE</code>) - the first segment of the path |
| * is the name of a classpath variable. If this classpath variable |
| * is bound to the path <it>P</it>, the path of the corresponding classpath entry |
| * is computed by appending to <it>P</it> the segments of the returned |
| * path without the variable.</li> |
| * <li> A container entry (<code>CONTAINER</code>) - the first segment of the path is denoting |
| * the unique container identifier (for which a <code>ClasspathContainerInitializer</code> could be |
| * registered), and the remaining segments are used as additional hints for resolving the container entry to |
| * an actual <code>IClasspathContainer</code>.</li> |
| */ |
| private final IPath path; |
| |
| /** |
| * Patterns allowing to include/exclude portions of the resource tree denoted by this entry path. |
| */ |
| private final @Nullable ImList<IPath> inclusionPatterns; |
| private volatile @Nullable ImList<String> fullInclusionPatterns; |
| private final @Nullable ImList<IPath> exclusionPatterns; |
| private volatile @Nullable ImList<String> fullExclusionPatterns; |
| |
| |
| /** |
| * Describes the path to the source archive associated with this |
| * classpath entry, or <code>null</code> if this classpath entry has no |
| * source attachment. |
| * <p> |
| * Only library and variable classpath entries may have source attachments. |
| * For library classpath entries, the result path (if present) locates a source |
| * archive. For variable classpath entries, the result path (if present) has |
| * an analogous form and meaning as the variable path, namely the first segment |
| * is the name of a classpath variable. |
| */ |
| private final @Nullable IPath sourceAttachmentPath; |
| |
| /** |
| * Describes the path within the source archive where package fragments |
| * are located. An empty path indicates that packages are located at |
| * the root of the source archive. Returns a non-<code>null</code> value |
| * if and only if <code>getSourceAttachmentPath</code> returns |
| * a non-<code>null</code> value. |
| */ |
| private final @Nullable IPath sourceAttachmentRootPath; |
| |
| /** |
| * See {@link BuildpathElement#getReferencingEntry()} |
| */ |
| private final @Nullable BuildpathElement referencingElement; |
| |
| /** |
| * Specific output location (for this source entry) |
| */ |
| private final @Nullable IPath specificOutputPath; |
| |
| /** |
| * The export flag |
| */ |
| private final boolean isExported; |
| |
| /** |
| * The extra attributes |
| */ |
| private final ImList<BuildpathAttribute> extraAttributes; |
| |
| |
| /** |
| * Creates a class path entry of the specified kind with the given path. |
| */ |
| public BasicBuildpathElement(final BuildpathElementType type, |
| final IPath path, final @Nullable ImList<IPath> inclusionPatterns, final @Nullable ImList<IPath> exclusionPatterns, |
| final @Nullable IPath sourceAttachmentPath, final @Nullable IPath sourceAttachmentRootPath, |
| final @Nullable IPath specificOutputLocation, |
| final @Nullable BuildpathElement referencingEntry, |
| final boolean isExported, |
| final @Nullable ImList<BuildpathAttribute> extraAttributes) { |
| this.type= nonNullAssert(type); |
| this.path= nonNullAssert(path); |
| this.inclusionPatterns= inclusionPatterns; |
| this.fullInclusionPatterns= UNINITIALIZED_PATTERNS; |
| this.exclusionPatterns= exclusionPatterns; |
| this.fullExclusionPatterns= UNINITIALIZED_PATTERNS; |
| this.referencingElement= referencingEntry; |
| |
| this.sourceAttachmentPath= sourceAttachmentPath; |
| this.sourceAttachmentRootPath= sourceAttachmentRootPath; |
| this.specificOutputPath= specificOutputLocation; |
| |
| this.isExported= isExported; |
| |
| this.extraAttributes= (extraAttributes != null) ? extraAttributes : ImCollections.<BuildpathAttribute>emptyList(); |
| } |
| |
| |
| @Override |
| public final BuildpathElementType getType() { |
| return this.type; |
| } |
| |
| @Override |
| public final String getTypeName() { |
| return this.type.getName(); |
| } |
| |
| @Override |
| public final IPath getPath() { |
| return this.path; |
| } |
| |
| @Override |
| public final @Nullable ImList<IPath> getInclusionPatterns() { |
| return this.inclusionPatterns; |
| } |
| |
| @Override |
| public final @Nullable ImList<IPath> getExclusionPatterns() { |
| return this.exclusionPatterns; |
| } |
| |
| private @Nullable ImList<String> createFullPatterns(final @Nullable ImList<IPath> patterns) { |
| if (patterns == null || patterns.isEmpty()) { |
| return null; |
| } |
| final int length= patterns.size(); |
| final String[] fullPatterns= new @NonNull String[length]; |
| final IPath prefixPath= this.path.removeTrailingSeparator(); |
| for (int i= 0; i < length; i++) { |
| fullPatterns[i]= prefixPath.append(patterns.get(i)).toString(); |
| } |
| return ImCollections.newList(fullPatterns); |
| } |
| |
| public @Nullable ImList<String> getFullInclusionPatterns() { |
| ImList<String> patterns= this.fullInclusionPatterns; |
| if (patterns == UNINITIALIZED_PATTERNS) { |
| patterns= this.fullInclusionPatterns= createFullPatterns(this.inclusionPatterns); |
| } |
| return patterns; |
| } |
| |
| public @Nullable ImList<String> getFullExclusionPatterns() { |
| ImList<String> patterns= this.fullExclusionPatterns; |
| if (patterns == UNINITIALIZED_PATTERNS) { |
| patterns= this.fullExclusionPatterns= createFullPatterns(this.exclusionPatterns); |
| } |
| return patterns; |
| } |
| |
| @Override |
| public @Nullable IPath getOutputPath() { |
| return this.specificOutputPath; |
| } |
| |
| |
| @Override |
| public ImList<BuildpathAttribute> getExtraAttributes() { |
| return this.extraAttributes; |
| } |
| |
| public @Nullable BuildpathAttribute getAttribute(final String name) { |
| for (final BuildpathAttribute attribute : this.extraAttributes) { |
| if (attribute.getName().equals(name)) { |
| return attribute; |
| } |
| } |
| return null; |
| } |
| |
| |
| @Override |
| public @Nullable IPath getSourceAttachmentPath() { |
| return this.sourceAttachmentPath; |
| } |
| |
| public @Nullable IPath getSourceAttachmentRootPath() { |
| return this.sourceAttachmentRootPath; |
| } |
| |
| public @Nullable BuildpathElement getReferencingEntry() { |
| return this.referencingElement; |
| } |
| |
| @Override |
| public boolean isExported() { |
| return this.isExported; |
| } |
| |
| |
| @Override |
| public int hashCode() { |
| return this.type.hashCode() ^ this.path.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(final @Nullable Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj instanceof BasicBuildpathElement) { |
| final BasicBuildpathElement other= (BasicBuildpathElement)obj; |
| return (this.type == other.type |
| && this.isExported == other.isExported() |
| && this.path.equals(other.getPath()) |
| && Objects.equals(this.sourceAttachmentPath, other.sourceAttachmentPath) |
| && Objects.equals(getSourceAttachmentRootPath(), other.sourceAttachmentRootPath) |
| && BuildpathUtils.equalPatterns(this.inclusionPatterns, other.getInclusionPatterns()) |
| && BuildpathUtils.equalPatterns(this.exclusionPatterns, other.getExclusionPatterns()) |
| && Objects.equals(this.specificOutputPath, other.specificOutputPath) |
| && this.extraAttributes.equals(other.extraAttributes) ); |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| final ObjectUtils.ToStringBuilder sb= new ObjectUtils.ToStringBuilder("BasicBuildpathElement"); //$NON-NLS-1$ |
| sb.append(" ["); //$NON-NLS-1$ |
| sb.append(this.type.getName()); |
| sb.append("]:"); //$NON-NLS-1$ |
| sb.append(getPath().toString()); |
| sb.addProp("including", getInclusionPatterns()); //$NON-NLS-1$ |
| sb.addProp("excluding", getExclusionPatterns()); //$NON-NLS-1$ |
| sb.addProp("sourcePath", getSourceAttachmentPath()); //$NON-NLS-1$ |
| { final IPath rootPath= getSourceAttachmentRootPath(); |
| if (rootPath != null) { |
| sb.append(':'); |
| sb.append(rootPath.toString()); |
| } |
| } |
| sb.addProp("outputPath", getOutputPath()); //$NON-NLS-1$ |
| sb.addProp("isExported", this.isExported); |
| final ImList<BuildpathAttribute> attributes= getExtraAttributes(); |
| if (!attributes.isEmpty()) { |
| sb.addProp("extraAttributes", attributes); //$NON-NLS-1$ |
| } |
| return sb.toString(); |
| } |
| |
| } |