// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.android;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;

import com.android.SdkConstants;
import com.android.annotations.VisibleForTesting;
import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.ide.common.resources.configuration.ResourceQualifier;
import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import com.google.common.base.Ascii;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
import com.google.devtools.build.android.proto.SerializeFormat;
import com.google.devtools.build.android.resources.ResourceTypeEnum;
import com.google.devtools.build.android.xml.ResourcesAttribute;
import com.google.errorprone.annotations.CheckReturnValue;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.concurrent.Immutable;

/**
 * Represents a fully qualified name for an android resource.
 *
 * <p>Each resource name consists of the resource package, name, type, and qualifiers.
 */
// TODO(b/146498565): remove and/or replace.  For normal resources this can just be a ResourceName
// with Configuration, and the latter can come from aapt2 directly.  tools:* attributes should be a
// separate DataKey; as FullyQualifiedName they all have the same package, same singleton
// VirtualType, and same empty qualifiers.
@Immutable
public class FullyQualifiedName implements DataKey {
  public static final String DEFAULT_PACKAGE = "res-auto";
  private static final Joiner DASH_JOINER = Joiner.on('-');
  // To save on memory, always return one instance for each FullyQualifiedName.
  // Using a HashMap to deduplicate the instances -- the key retrieves a single instance.
  private static final ConcurrentMap<FullyQualifiedName, FullyQualifiedName> instanceCache =
      new ConcurrentHashMap<>();

  private static final AtomicInteger cacheHit = new AtomicInteger(0);
  private final String pkg;
  // TODO(b/146498565): use com.android.aapt.ConfigurationOuterClass.Configuration.
  private final ImmutableList<String> qualifiers;
  private final Type type;
  private final String name;

  private FullyQualifiedName(String pkg, ImmutableList<String> qualifiers, Type type, String name) {
    Preconditions.checkArgument(!pkg.isEmpty());
    this.pkg = pkg;
    this.qualifiers = qualifiers;
    this.type = type;
    this.name = name;
  }

  private static Type createTypeFrom(String rawType) {
    ResourceType resourceType = ResourceTypeEnum.get(rawType);
    VirtualType virtualType = VirtualType.getEnum(rawType);
    if (resourceType != null) {
      return new ResourceTypeWrapper(resourceType);
    } else if (virtualType != null) {
      return virtualType;
    }
    return null;
  }

  /**
   * Creates a new FullyQualifiedName with normalized qualifiers.
   *
   * @param rawPkg The resource package of the name. If unknown the default should be "res-auto"
   * @param qualifiers The resource qualifiers of the name, such as "en" or "xhdpi".
   * @param type The type of the name.
   * @param name The name of the name.
   * @return A new FullyQualifiedName.
   */
  public static FullyQualifiedName of(
      String rawPkg, List<String> qualifiers, Type type, String name) {
    checkNotNull(rawPkg);
    checkNotNull(qualifiers);
    checkNotNull(type);
    checkNotNull(name);
    ImmutableList<String> immutableQualifiers = ImmutableList.copyOf(qualifiers);
    String pkg = rawPkg.isEmpty() ? DEFAULT_PACKAGE : rawPkg;
    // TODO(corysmith): Address the GC thrash this creates by managing a simplified, mutable key to
    // do the instance check.
    FullyQualifiedName fqn = new FullyQualifiedName(pkg, immutableQualifiers, type, name);
    // Use putIfAbsent to get the canonical instance, if there. If it isn't, putIfAbsent will
    // return null, and we should return the current instance.
    FullyQualifiedName cached = instanceCache.putIfAbsent(fqn, fqn);
    if (cached == null) {
      return fqn;
    } else {
      cacheHit.incrementAndGet();
      return cached;
    }
  }

  /**
   * Creates a new FullyQualifiedName with normalized qualifiers.
   *
   * @param pkg The resource package of the name. If unknown the default should be "res-auto"
   * @param qualifiers The resource qualifiers of the name, such as "en" or "xhdpi".
   * @param type The resource type of the name.
   * @param name The name of the name.
   * @return A new FullyQualifiedName.
   */
  static FullyQualifiedName of(
      String pkg, List<String> qualifiers, ResourceType type, String name) {
    return of(pkg, qualifiers, new ResourceTypeWrapper(type), name);
  }

  public static FullyQualifiedName fromProto(SerializeFormat.DataKey protoKey) {
    return of(
        protoKey.getKeyPackage(),
        protoKey.getQualifiersList(),
        createTypeFrom(protoKey.getResourceType()),
        protoKey.getKeyValue());
  }

  // Note that while "$" is not allowed in source code, it's used in generated names (precisely to
  // avoid colliding with source code).
  static final Pattern QUALIFIED_REFERENCE =
      Pattern.compile("^((?<package>[^:]+):)?(?<type>\\w+)/(?<name>[A-Za-z0-9_.$]+)$");

  public static FullyQualifiedName fromReference(
      String qualifiedReference, Optional<String> packageName) {
    final Matcher matcher = QUALIFIED_REFERENCE.matcher(qualifiedReference);
    Preconditions.checkArgument(
        matcher.matches(),
        "%s is not a reference. Expected %s",
        qualifiedReference,
        QUALIFIED_REFERENCE.pattern());
    return of(
        Optional.ofNullable(emptyToNull(matcher.group("package")))
            .orElse(packageName.orElse(DEFAULT_PACKAGE)),
        ImmutableList.of(),
        ResourceTypeEnum.get(matcher.group("type")),
        matcher.group("name"));
  }

  public static void logCacheUsage(Logger logger) {
    logger.fine(
        String.format(
            "Total FullyQualifiedName instance cache hits %s out of %s",
            cacheHit.intValue(), instanceCache.size()));
  }

  /**
   * Returns a string path representation of the FullyQualifiedName.
   *
   * <p>Non-values Android Resource have a well defined file layout: From the resource directory,
   * they reside in &lt;resource type&gt;[-&lt;qualifier&gt;]/&lt;resource name&gt;[.extension]
   *
   * @param source The original source of the file-based resource's FullyQualifiedName
   * @return A string representation of the FullyQualifiedName with the provided extension.
   */
  public String toPathString(Path source) {
    String sourceExtension = FullyQualifiedName.Factory.getSourceExtension(source);
    return Paths.get(
            DASH_JOINER.join(
                ImmutableList.<String>builder().add(type.getName()).addAll(qualifiers).build()),
            name + sourceExtension)
        .toString();
  }

  @Override
  public String toPrettyString() {
    // TODO(corysmith): Add package when we start tracking it.
    return String.format(
        "%s%s/%s",
        DEFAULT_PACKAGE.equals(pkg) ? "" : pkg + ':',
        DASH_JOINER.join(
            ImmutableList.<String>builder().add(type.getName()).addAll(qualifiers).build()),
        name);
  }

  /**
   * Returns the string path representation of the values directory and qualifiers.
   *
   * <p>Certain resource types live in the "values" directory. This will calculate the directory and
   * ensure the qualifiers are represented.
   */
  // TODO(corysmith): Combine this with toPathString to clean up the interface of FullyQualifiedName
  // logically, the FullyQualifiedName should just be able to provide the relative path string for
  // the resource.
  public String valuesPath() {
    return Paths.get(
            DASH_JOINER.join(
                ImmutableList.<String>builder().add("values").addAll(qualifiers).build()),
            "values.xml")
        .toString();
  }

  @VisibleForTesting
  public String asUnqualifedName() {
    return String.format(
        "%s/%s",
        DASH_JOINER.join(
            ImmutableList.<String>builder().add(type.getName()).addAll(qualifiers).build()),
        name);
  }

  public String name() {
    return name;
  }

  public boolean isInPackage(String packageName) {
    return pkg.equals(packageName);
  }

  /** Provides the name qualified by the package it belongs to. */
  public String qualifiedName() {
    return (pkg.equals(DEFAULT_PACKAGE) ? "" : pkg + ":") + name;
  }

  public String asQualifiedReference() {
    return String.format(
        "%s%s/%s", (pkg.equals(DEFAULT_PACKAGE) ? "" : pkg + ":"), type.getName(), name);
  }

  public ResourceType type() {
    if (type instanceof ResourceTypeWrapper) {
      return ((ResourceTypeWrapper) type).resourceType;
    }
    return null;
  }

  public boolean isOverwritable() {
    return type.isOverwritable(this);
  }

  /** Creates a FullyQualifiedName from this one with a different package. */
  @CheckReturnValue
  public FullyQualifiedName replacePackage(String newPackage) {
    if (pkg.equals(newPackage)) {
      return this;
    }
    return of(newPackage, qualifiers, type, name);
  }

  @Override
  public int hashCode() {
    return Objects.hash(pkg, qualifiers, type, name);
  }

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof FullyQualifiedName)) {
      return false;
    }

    FullyQualifiedName other = getClass().cast(obj);
    return Objects.equals(pkg, other.pkg)
        && Objects.equals(type, other.type)
        && Objects.equals(name, other.name)
        && Objects.equals(qualifiers, other.qualifiers);
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(getClass())
        .add("pkg", pkg)
        .add("qualifiers", qualifiers)
        .add("type", type)
        .add("name", name)
        .toString();
  }

  @Override
  public int compareTo(DataKey otherKey) {
    if (!(otherKey instanceof FullyQualifiedName)) {
      return getKeyType().compareTo(otherKey.getKeyType());
    }
    FullyQualifiedName other = (FullyQualifiedName) otherKey;
    if (!pkg.equals(other.pkg)) {
      return pkg.compareTo(other.pkg);
    }
    if (!type.equals(other.type)) {
      return type.compareTo(other.type);
    }
    if (!name.equals(other.name)) {
      return name.compareTo(other.name);
    }
    if (!qualifiers.equals(other.qualifiers)) {
      if (qualifiers.size() != other.qualifiers.size()) {
        return qualifiers.size() - other.qualifiers.size();
      }
      // This works because the qualifiers are always in an ordered sequence.
      return qualifiers.toString().compareTo(other.qualifiers.toString());
    }
    return 0;
  }

  @Override
  public KeyType getKeyType() {
    return KeyType.FULL_QUALIFIED_NAME;
  }

  @Override
  public boolean shouldDetectConflicts() {
    // Ignore conflicts among pseudolocales.
    return qualifiers.stream()
        .noneMatch(q -> Ascii.equalsIgnoreCase(q, "en-rXA") || Ascii.equalsIgnoreCase(q, "ar-rXB"));
  }

  @Override
  public void serializeTo(OutputStream out, int valueSize) throws IOException {
    toSerializedBuilder().setValueSize(valueSize).build().writeDelimitedTo(out);
  }

  public SerializeFormat.DataKey.Builder toSerializedBuilder() {
    return SerializeFormat.DataKey.newBuilder()
        .setKeyPackage(pkg)
        .setResourceType(type.getName())
        .addAllQualifiers(qualifiers)
        .setKeyValue(name);
  }

  /** The non-resource {@link Type}s of a {@link FullyQualifiedName}. */
  public enum VirtualType implements Type {
    RESOURCES_ATTRIBUTE("<resources>", "Resources Attribute");

    private final String name;
    private final String displayName;

    private VirtualType(String name, String displayName) {
      this.name = name;
      this.displayName = displayName;
    }

    /** Returns the enum represented by the {@code name}. */
    public static VirtualType getEnum(String name) {
      for (VirtualType type : values()) {
        if (type.name.equals(name)) {
          return type;
        }
      }
      return null;
    }

    /** Returns an array with all the names defined by this enum. */
    public static String[] getNames() {
      VirtualType[] values = values();
      String[] names = new String[values.length];
      for (int i = values.length - 1; i >= 0; --i) {
        names[i] = values[i].getName();
      }
      return names;
    }

    /** Returns the resource type name. */
    @Override
    public String getName() {
      return name;
    }

    /** Returns a translated display name for the resource type. */
    public String getDisplayName() {
      return displayName;
    }

    @Override
    public ConcreteType getType() {
      return ConcreteType.VIRTUAL_TYPE;
    }

    @Override
    public boolean isOverwritable(FullyQualifiedName fqn) {
      if (this == RESOURCES_ATTRIBUTE) {
        return !ResourcesAttribute.AttributeType.from(fqn.name()).isCombining();
      }
      return true;
    }

    @Override
    public int compareTo(Type other) {
      if (!(other instanceof VirtualType)) {
        return getType().compareTo(other.getType());
      }
      return compareTo(((VirtualType) other));
    }

    @Override
    public String toString() {
      return getName();
    }
  }

  /** Represents the type of a {@link FullyQualifiedName}. */
  public interface Type {
    String getName();

    ConcreteType getType();

    boolean isOverwritable(FullyQualifiedName fqn);

    int compareTo(Type other);

    @Override
    boolean equals(Object obj);

    @Override
    int hashCode();

    @Override
    String toString();

    /**
     * The category of type that a {@link Type} can be.
     *
     * <p><em>Note:</em> used for strict ordering of {@link FullyQualifiedName}s.
     */
    enum ConcreteType {
      RESOURCE_TYPE,
      VIRTUAL_TYPE;
    }
  }

  private static class ResourceTypeWrapper implements Type {
    private final ResourceType resourceType;

    public ResourceTypeWrapper(ResourceType resourceType) {
      this.resourceType = resourceType;
    }

    @Override
    public String getName() {
      return resourceType.getName();
    }

    @Override
    public ConcreteType getType() {
      return ConcreteType.RESOURCE_TYPE;
    }

    @Override
    public boolean isOverwritable(FullyQualifiedName fqn) {
      return !(resourceType == ResourceType.ID
          || resourceType == ResourceType.PUBLIC
          || resourceType == ResourceType.STYLEABLE);
    }

    @Override
    public int compareTo(Type other) {
      if (!(other instanceof ResourceTypeWrapper)) {
        return getType().compareTo(other.getType());
      }
      return resourceType.compareTo(((ResourceTypeWrapper) other).resourceType);
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof ResourceTypeWrapper)) {
        return false;
      }
      ResourceTypeWrapper other = (ResourceTypeWrapper) obj;
      return Objects.equals(resourceType, other.resourceType);
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(resourceType);
    }

    @Override
    public String toString() {
      return resourceType.toString();
    }
  }

  /** Represents the configuration qualifiers in a resource directory. */
  public static class Qualifiers {

    private static final Qualifiers EMPTY_QUALIFIERS =
        new Qualifiers(null, ImmutableList.of(), false);

    // Qualifiers are reasonably expensive to create, so cache them on directory names.
    private static final ConcurrentMap<String, Qualifiers> qualifierCache =
        new ConcurrentHashMap<>();

    public static final String INVALID_QUALIFIERS = "%s contains invalid qualifiers.";
    private final ResourceFolderType folderType;
    private final ImmutableList<String> qualifiers;
    private boolean defaultLocale;

    private Qualifiers(
        ResourceFolderType folderType, ImmutableList<String> qualifiers, boolean defaultLocale) {
      this.folderType = folderType;
      this.qualifiers = qualifiers;
      this.defaultLocale = defaultLocale;
    }

    public static Qualifiers parseFrom(String directoryName) {
      return qualifierCache.computeIfAbsent(
          directoryName, d -> getQualifiers(Splitter.on(SdkConstants.RES_QUALIFIER_SEP).split(d)));
    }

    private static Qualifiers getQualifiers(String... dirNameAndQualifiers) {
      return getQualifiers(Arrays.asList(dirNameAndQualifiers));
    }

    private static Qualifiers getQualifiers(Iterable<String> dirNameAndQualifiers) {
      PeekingIterator<String> rawQualifiers =
          Iterators.peekingIterator(dirNameAndQualifiers.iterator());
      // Remove directory name
      final ResourceFolderType folderType = ResourceFolderType.getTypeByName(rawQualifiers.next());

      // If there is no folder type, there are no qualifiers to parse.
      if (folderType == null) {
        return EMPTY_QUALIFIERS;
      }

      List<String> handledQualifiers = new ArrayList<>();
      // Do some substitution of language/region qualifiers.
      while (rawQualifiers.hasNext()) {
        handledQualifiers.add(rawQualifiers.next());
      }
      // Create a configuration
      FolderConfiguration config = FolderConfiguration.getConfigFromQualifiers(handledQualifiers);
      // FolderConfiguration returns an unhelpful null when it considers the qualifiers to be
      // invalid.
      if (config == null) {
        throw new IllegalArgumentException(
            String.format(INVALID_QUALIFIERS, DASH_JOINER.join(dirNameAndQualifiers)));
      }
      config.normalizeByAddingImpliedVersionQualifier();

      ImmutableList.Builder<String> builder = ImmutableList.<String>builder();
      // index 3 is past the country code, network code, and locale indices.
      for (int i = 0; i < FolderConfiguration.getQualifierCount(); ++i) {
        addIfNotNull(config.getQualifier(i), builder);
      }
      ResourceQualifier localeQualifier = config.getLocaleQualifier();
      return new Qualifiers(
          folderType,
          builder.build(),
          localeQualifier == null || localeQualifier == localeQualifier.getNullQualifier());
    }

    private static void addIfNotNull(
        ResourceQualifier qualifier, ImmutableList.Builder<String> builder) {
      if (qualifier != null && qualifier != qualifier.getNullQualifier()) {
        builder.add(qualifier.getFolderSegment());
      }
    }

    /** Returns the qualifiers as a list of strings. */
    public List<String> asList() {
      return qualifiers;
    }

    public ResourceFolderType asFolderType() {
      return folderType;
    }

    /** Creates a Qualifiers assuming that they are in the values directory. */
    @VisibleForTesting
    public static Qualifiers forValuesFolderFrom(List<String> qualifiers) {
      return Qualifiers.getQualifiers(
          ImmutableList.builder().add("values").addAll(qualifiers).build().toArray(new String[0]));
    }

    public boolean containDefaultLocale() {
      return defaultLocale;
    }
  }

  /** A factory for parsing a generating FullyQualified names with qualifiers and package. */
  public static class Factory {

    public static final String INVALID_QUALIFIED_NAME_MESSAGE_NO_MATCH =
        String.format(
            "%%s is not a valid qualified name. "
                + "It should be in the pattern [package:]{%s}/name",
            Joiner.on(",")
                .join(
                    ImmutableList.<String>builder()
                        .addAll(ResourceType.getClassNames())
                        .add(VirtualType.getNames())
                        .build()));
    public static final String INVALID_QUALIFIED_NAME_MESSAGE_NO_TYPE_OR_NAME =
        String.format(
            "Could not find either resource type (%%s) or name (%%s) in %%s. "
                + "It should be in the pattern [package:]{%s}/name",
            Joiner.on(",")
                .join(
                    ImmutableList.<String>builder()
                        .addAll(ResourceType.getClassNames())
                        .add(VirtualType.getNames())
                        .build()));
    private static final Pattern PARSING_REGEX =
        Pattern.compile(
            "(?:(?<package>[^:]+):){0,1}(?<type>[^-/]+)(?:[^/]*)/(?:(?:(?<namespace>\\{[^}]+\\}))"
                + "|(?:(?<misplacedPackage>[^:]+):)){0,1}(?<name>.+)");
    // private final ImmutableList<String> qualifiers;

    private final String pkg;

    private final Qualifiers qs;

    private Factory(Qualifiers qualifiers, String pkg) {
      // this.qualifiers = qualifiers;
      this.pkg = pkg;
      this.qs = qualifiers;
    }

    /** Creates a factory with default package from a directory name split on '-'. */
    @VisibleForTesting
    public static Factory fromDirectoryName(String... dirNameAndQualifiers) {
      return using(Qualifiers.getQualifiers(dirNameAndQualifiers), DEFAULT_PACKAGE);
    }

    /** Creates a factory with default package from a directory with '-' separating qualifiers. */
    public static Factory fromDirectoryName(String dirNameAndQualifiers) {
      return using(Qualifiers.parseFrom(dirNameAndQualifiers), DEFAULT_PACKAGE);
    }

    @VisibleForTesting
    public static Factory from(List<String> qualifiers, String pkg) {
      return using(Qualifiers.forValuesFolderFrom(qualifiers), pkg);
    }

    @VisibleForTesting
    public static Factory from(List<String> qualifiers) {
      return from(qualifiers, DEFAULT_PACKAGE);
    }

    /** Creates a factory with the qualifiers and package. */
    public static Factory using(Qualifiers qualifiers) {
      return using(qualifiers, DEFAULT_PACKAGE);
    }

    /** Creates a factory with the qualifiers and package. */
    public static Factory using(Qualifiers qualifiers, String pkg) {
      return new Factory(qualifiers, pkg.isEmpty() ? DEFAULT_PACKAGE : pkg);
    }

    private static String deriveRawFullyQualifiedName(Path source) {
      if (source.getNameCount() < 2) {
        throw new IllegalArgumentException(
            String.format(
                "The resource path %s is too short. "
                    + "The path is expected to be <resource type>/<file name>.",
                source));
      }
      // Compose the `pathWithExtension` manually to ensure it uses a forward slash.
      // Using Path.subpath would return a backslash-using path on Windows.
      String pathWithExtension = source.getParent().getFileName() + "/" + source.getFileName();
      int extensionStart = pathWithExtension.indexOf('.');
      if (extensionStart > 0) {
        return pathWithExtension.substring(0, extensionStart);
      }
      return pathWithExtension;
    }

    // Grabs the extension portion of the path removed by deriveRawFullyQualifiedName.
    private static String getSourceExtension(Path source) {
      // TODO(corysmith): Find out if there is a filename parser utility.
      String fileName = source.getFileName().toString();
      int extensionStart = fileName.indexOf('.');
      if (extensionStart > 0) {
        return fileName.substring(extensionStart);
      }
      return "";
    }

    public FullyQualifiedName create(Type type, String name, String pkg) {
      return FullyQualifiedName.of(pkg, qs.asList(), type, name);
    }

    public FullyQualifiedName create(ResourceType type, String name) {
      return create(new ResourceTypeWrapper(type), name, pkg);
    }

    public FullyQualifiedName create(ResourceType type, String name, String pkg) {
      return create(new ResourceTypeWrapper(type), name, pkg);
    }

    public FullyQualifiedName create(VirtualType type, String name) {
      return create(type, name, pkg);
    }

    /**
     * Parses a FullyQualifiedName from a string.
     *
     * @param raw A string in the expected format from
     *     [&lt;package&gt;:]&lt;ResourceType.name&gt;/&lt;resource name&gt;.
     * @throws IllegalArgumentException when the raw string is not valid qualified name.
     */
    public FullyQualifiedName parse(String raw) {
      Matcher matcher = PARSING_REGEX.matcher(raw);
      if (!matcher.matches()) {
        throw new IllegalArgumentException(
            String.format(INVALID_QUALIFIED_NAME_MESSAGE_NO_MATCH, raw));
      }
      String parsedPackage =
          firstNonNull(matcher.group("package"), matcher.group("misplacedPackage"), pkg);

      Type type = createTypeFrom(matcher.group("type"));
      String name =
          matcher.group("namespace") != null
              ? matcher.group("namespace") + matcher.group("name")
              : matcher.group("name");

      if (type == null || name == null) {
        throw new IllegalArgumentException(
            String.format(INVALID_QUALIFIED_NAME_MESSAGE_NO_TYPE_OR_NAME, type, name, raw));
      }

      return FullyQualifiedName.of(parsedPackage, qs.asList(), type, name);
    }

    /**
     * Generates a FullyQualifiedName for a file-based resource given the source Path.
     *
     * @param sourcePath the path of the file-based resource.
     * @throws IllegalArgumentException if the file-based resource has an invalid filename
     */
    public FullyQualifiedName parse(Path sourcePath) {
      return parse(deriveRawFullyQualifiedName(sourcePath));
    }

    private String firstNonNull(String... values) {
      for (String value : values) {
        if (value != null) {
          return value;
        }
      }
      throw new NullPointerException("Expected a nonnull value.");
    }
  }
}
