001/*
002 * Copyright (C) 2022 - 2023, the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *    http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.github.ascopes.jct.filemanagers;
017
018import io.github.ascopes.jct.containers.ModuleContainerGroup;
019import io.github.ascopes.jct.containers.OutputContainerGroup;
020import io.github.ascopes.jct.containers.PackageContainerGroup;
021import io.github.ascopes.jct.workspaces.PathRoot;
022import java.io.IOException;
023import java.util.Collection;
024import java.util.Set;
025import javax.tools.JavaFileManager;
026import javax.tools.JavaFileObject;
027import javax.tools.JavaFileObject.Kind;
028import org.apiguardian.api.API;
029import org.apiguardian.api.API.Status;
030
031/**
032 * Extension around a {@link JavaFileManager} that allows adding of {@link PathRoot} objects to the
033 * manager.
034 *
035 * @author Ashley Scopes
036 * @since 0.0.1
037 */
038@API(since = "0.0.1", status = Status.STABLE)
039public interface JctFileManager extends JavaFileManager {
040
041  /**
042   * Add a package-oriented path to a given location.
043   *
044   * <p>To add a module, first obtain the module location using
045   * {@link #getLocationForModule(Location, String)}, and pass that result to this call.
046   *
047   * @param location the location to use.
048   * @param path     the path to add.
049   * @see #getLocationForModule(Location, String)
050   */
051  void addPath(Location location, PathRoot path);
052
053  /**
054   * Add a collection of package-oriented paths to a given location.
055   *
056   * <p>To add a module, first obtain the module location using
057   * {@link #getLocationForModule(Location, String)}, and pass that result to this call.
058   *
059   * @param location the location to use.
060   * @param paths    the paths to add.
061   * @see #getLocationForModule(Location, String)
062   */
063  void addPaths(Location location, Collection<? extends PathRoot> paths);
064
065  /**
066   * Copy all containers from the first location to the second location.
067   *
068   * @param from the first location.
069   * @param to   the second location.
070   */
071  void copyContainers(Location from, Location to);
072
073  /**
074   * Register an empty container for the given location to indicate to the compiler that the feature
075   * exists, but has no configured paths.
076   *
077   * <p>This is needed to coerce the behaviour for annotation processing in some cases.
078   *
079   * <p>If the location already exists, then do not do anything.
080   *
081   * <p>If the location is an output location, then this operation does not make any sense, since
082   * an empty location cannot have files output to it. In this case, you will likely get an
083   * exception.
084   *
085   * <p>Likewise, this operation does not make sense for module locations within a module-oriented
086   * location group, so this operation will fail with an error for those inputs as well.
087   *
088   * @param location the location to apply an empty container for.
089   * @throws IllegalArgumentException if the location is an output location or a module location.
090   */
091  void createEmptyLocation(Location location);
092
093  /**
094   * Get the associated effective release.
095   *
096   * @return the effective release.
097   * @since 0.0.1 (0.0.1-M8)
098   */
099  String getEffectiveRelease();
100
101  /**
102   * Get the container group for the given package-oriented location.
103   *
104   * @param location the package oriented location.
105   * @return the container group, or null if one does not exist.
106   */
107  PackageContainerGroup getPackageContainerGroup(Location location);
108
109  /**
110   * Get a collection of all package container impl in this file manager.
111   *
112   * @return the package container impl.
113   */
114  Collection<PackageContainerGroup> getPackageContainerGroups();
115
116  /**
117   * Get the container group for the given module-oriented location.
118   *
119   * @param location the module oriented location.
120   * @return the container group, or null if one does not exist.
121   */
122  ModuleContainerGroup getModuleContainerGroup(Location location);
123
124  /**
125   * Get a collection of all module container impl in this file manager.
126   *
127   * @return the module container impl.
128   */
129  Collection<ModuleContainerGroup> getModuleContainerGroups();
130
131  /**
132   * Get the container group for the given output-oriented location.
133   *
134   * @param location the output oriented location.
135   * @return the container group, or null if one does not exist.
136   */
137  OutputContainerGroup getOutputContainerGroup(Location location);
138
139  /**
140   * Get a collection of all output container impl in this file manager.
141   *
142   * @return the output container impl.
143   */
144  Collection<OutputContainerGroup> getOutputContainerGroups();
145
146  /**
147   * List all file objects in the given location matching the given criteria.
148   *
149   * @param location    the location to search in.
150   * @param packageName the package name to search in, or {@code ""} to search in the root
151   *                    location.
152   * @param kinds       the kinds of file to return, or {@link Set#of} {@code (} {@link Kind#OTHER}
153   *                    {@code )} to find all files.
154   * @param recurse     {@code true} to recurse into subpackages, {@code false} to only check the
155   *                    current package.
156   * @return a collection of unique file objects that were found.
157   * @throws IOException if an IO error occurs reading the file system.
158   */
159  @Override
160  Set<JavaFileObject> list(
161      Location location,
162      String packageName,
163      Set<Kind> kinds,
164      boolean recurse
165  ) throws IOException;
166}