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.ex.JctIllegalInputException; 019import io.github.ascopes.jct.utils.ToStringBuilder; 020import java.util.Objects; 021import javax.tools.JavaFileManager.Location; 022import org.apiguardian.api.API; 023import org.apiguardian.api.API.Status; 024import org.jspecify.annotations.Nullable; 025 026/** 027 * Handle that represents the location of a module. 028 * 029 * @author Ashley Scopes 030 * @since 0.0.1 031 */ 032@API(since = "0.0.1", status = Status.STABLE) 033public final class ModuleLocation implements Location { 034 035 private final Location parent; 036 private final String moduleName; 037 private final String name; 038 039 /** 040 * Initialize the location. 041 * 042 * @param parent the parent location. 043 * @param moduleName the module name. 044 * @throws JctIllegalInputException if the parent location is not an output location or a 045 * module-oriented location. 046 */ 047 public ModuleLocation(Location parent, String moduleName) { 048 Objects.requireNonNull(parent, "parent"); 049 Objects.requireNonNull(moduleName, "moduleName"); 050 051 if (!parent.isOutputLocation() && !parent.isModuleOrientedLocation()) { 052 throw new JctIllegalInputException( 053 "The parent of a module location must be either an output location " 054 + "or be module-oriented, but got " 055 + parent.getName() 056 ); 057 } 058 059 this.parent = parent; 060 this.moduleName = moduleName; 061 name = parent.getName() + "[" + moduleName + "]"; 062 } 063 064 /** 065 * Get the parent location. 066 * 067 * @return the parent location. 068 */ 069 public Location getParent() { 070 return parent; 071 } 072 073 /** 074 * Get the module name. 075 * 076 * @return the module name. 077 */ 078 public String getModuleName() { 079 return moduleName; 080 } 081 082 @Override 083 public String getName() { 084 return name; 085 } 086 087 @Override 088 public boolean isOutputLocation() { 089 return parent.isOutputLocation(); 090 } 091 092 @Override 093 public boolean isModuleOrientedLocation() { 094 // Module locations cannot be module-oriented, but their parents can be. 095 return false; 096 } 097 098 @Override 099 public boolean equals(@Nullable Object other) { 100 if (!(other instanceof ModuleLocation)) { 101 return false; 102 } 103 104 var that = (ModuleLocation) other; 105 106 return parent.equals(that.parent) 107 && moduleName.equals(that.moduleName); 108 } 109 110 @Override 111 public int hashCode() { 112 return Objects.hash(parent, moduleName); 113 } 114 115 @Override 116 public String toString() { 117 return new ToStringBuilder(this) 118 .attribute("parent", parent) 119 .attribute("moduleName", moduleName) 120 .toString(); 121 } 122}