// 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.xml.ResourcesAttribute;
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.CheckReturnValue;
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.
 */
@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;
  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 = ResourceType.getEnum(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());
  }

  static final Pattern QUALIFIED_REFERENCE =
      Pattern.compile("((?<package>[^:]+):)?(?<type>\\w+)/(?<name>\\w+)");

  public static FullyQualifiedName fromReference(
      String qualifiedReference, Optional<String> packageName) {
    final Matcher matcher = QUALIFIED_REFERENCE.matcher(qualifiedReference);
    Preconditions.checkArgument(
        matcher.find(),
        "%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(),
        ResourceType.getEnum(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()) {
        String qualifier = rawQualifiers.next();
        if ("es".equalsIgnoreCase(qualifier)
            && rawQualifiers.hasNext()
            && "419".equalsIgnoreCase(rawQualifiers.peek())) {
          // Replace the es-419.
          handledQualifiers.add("b+es+419");
          // Consume the next value, as it's been replaced.
          rawQualifiers.next();
        } else if ("sr".equalsIgnoreCase(qualifier)
            && rawQualifiers.hasNext()
            && "rlatn".equalsIgnoreCase(rawQualifiers.peek())) {
          // Replace the sr-rLatn.
          handledQualifiers.add("b+sr+Latn");
          // Consume the next value, as it's been replaced.
          rawQualifiers.next();
        } else {
          // This qualifier can probably be handled by FolderConfiguration.
          handledQualifiers.add(qualifier);
        }
      }
      // 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.normalize();

      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);
      }
      return new Qualifiers(folderType, builder.build(), config.getLocaleQualifier() == null);
    }

    private static void addIfNotNull(
        ResourceQualifier qualifier, ImmutableList.Builder<String> builder) {
      if (qualifier != null) {
        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 an 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()
                        .add(ResourceType.getNames())
                        .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()
                        .add(ResourceType.getNames())
                        .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);
    }

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

    /**
     * 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));
    }
  }
}
