diff --git a/src/tools/permissionstree/PermissionNodesGatherer.java b/src/tools/permissionstree/PermissionNodesGatherer.java new file mode 100644 index 000000000..5da8841c9 --- /dev/null +++ b/src/tools/permissionstree/PermissionNodesGatherer.java @@ -0,0 +1,113 @@ +package permissionstree; + +import fr.xephi.authme.permission.AdminPermission; +import fr.xephi.authme.permission.PermissionNode; +import fr.xephi.authme.permission.PlayerPermission; +import fr.xephi.authme.util.StringUtils; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Gatherer to generate up-to-date lists of the AuthMe permission nodes. + */ +public class PermissionNodesGatherer { + + /** The folder in which the implementations of {@link PermissionNode} reside. */ + private static final String PERMISSION_NODE_SOURCE_FOLDER = + "src/main/java/fr/xephi/authme/permission/"; + + /** + * Regular expression that should match the JavaDoc comment above an enum, including + * the name of the enum value. The first group (i.e. {@code \\1}) should be the JavaDoc description; + * the second group should contain the enum value. + */ + private static final Pattern JAVADOC_WITH_ENUM_PATTERN = Pattern.compile( + "/\\*\\*\\s+\\*" // Match starting '/**' and the '*' on the next line + + "(.*?)\\s+\\*/" // Capture everything until we encounter '*/' + + "\\s+([A-Z_]+)\\("); // Match the enum name (e.g. 'LOGIN'), until before the first '(' + + /** + * Return a sorted collection of all permission nodes. + * + * @return AuthMe permission nodes sorted alphabetically + */ + public Set gatherNodes() { + Set nodes = new TreeSet<>(); + for (PermissionNode perm : PlayerPermission.values()) { + nodes.add(perm.getNode()); + } + for (PermissionNode perm : AdminPermission.values()) { + nodes.add(perm.getNode()); + } + return nodes; + } + + /** + * Return a sorted collection of all permission nodes, including its JavaDoc description. + * + * @return Ordered map whose keys are the permission nodes and the values the associated JavaDoc + */ + public Map gatherNodesWithJavaDoc() { + Map result = new TreeMap<>(); + addDescriptionsForClass(PlayerPermission.class, result); + addDescriptionsForClass(AdminPermission.class, result); + return result; + } + + private & PermissionNode> void addDescriptionsForClass(Class clazz, + Map descriptions) { + String classSource = getSourceForClass(clazz); + Map sourceDescriptions = extractJavaDocFromSource(classSource); + + for (T perm : EnumSet.allOf(clazz)) { + String description = sourceDescriptions.get(perm.name()); + if (description == null) { + System.out.println("Note: Could not retrieve description for " + + clazz.getSimpleName() + "#" + perm.name()); + description = ""; + } + descriptions.put(perm.getNode(), description.trim()); + } + } + + private static Map extractJavaDocFromSource(String source) { + Map allMatches = new HashMap<>(); + Matcher matcher = JAVADOC_WITH_ENUM_PATTERN.matcher(source); + while (matcher.find()) { + String description = matcher.group(1); + String enumValue = matcher.group(2); + allMatches.put(enumValue, description); + } + return allMatches; + } + + /** + * Return the Java source code for the given implementation of {@link PermissionNode}. + * + * @param clazz The clazz to the get the source for + * @param The concrete class + * @return Source code of the file + */ + private static & PermissionNode> String getSourceForClass(Class clazz) { + String classFile = PERMISSION_NODE_SOURCE_FOLDER + clazz.getSimpleName() + ".java"; + Charset cs = Charset.forName("utf-8"); + try { + return StringUtils.join("\n", + Files.readAllLines(Paths.get(classFile), cs)); + } catch (IOException e) { + throw new RuntimeException("Failed to get the source for class '" + clazz.getSimpleName() + "'"); + } + } + +} diff --git a/src/tools/permissionstree/PermissionNodesListCreater.java b/src/tools/permissionstree/PermissionNodesListCreater.java deleted file mode 100644 index bfc1a3b73..000000000 --- a/src/tools/permissionstree/PermissionNodesListCreater.java +++ /dev/null @@ -1,26 +0,0 @@ -package permissionstree; - -import fr.xephi.authme.permission.AdminPermission; -import fr.xephi.authme.permission.PermissionNode; -import fr.xephi.authme.permission.PlayerPermission; - -import java.util.Set; -import java.util.TreeSet; - -/** - * Generate all permission nodes like a tree. - */ -public class PermissionNodesListCreater { - - public Set gatherNodes() { - Set nodes = new TreeSet<>(); - for (PermissionNode perm : PlayerPermission.values()) { - nodes.add(perm.getNode()); - } - for (PermissionNode perm : AdminPermission.values()) { - nodes.add(perm.getNode()); - } - return nodes; - } - -} diff --git a/src/tools/permissionstree/PermissionsListWriter.java b/src/tools/permissionstree/PermissionsListWriter.java index 2f3e40f59..7d1cd1c26 100644 --- a/src/tools/permissionstree/PermissionsListWriter.java +++ b/src/tools/permissionstree/PermissionsListWriter.java @@ -4,6 +4,7 @@ import fr.xephi.authme.util.StringUtils; import utils.CommentType; import utils.GeneratedFileWriter; +import java.util.Map; import java.util.Scanner; import java.util.Set; @@ -18,14 +19,15 @@ public class PermissionsListWriter { public static void main(String[] args) { // Ask if result should be written to file Scanner scanner = new Scanner(System.in); - System.out.println("Write to file? [y = yes]"); - String answer = scanner.next(); - boolean writeToFile = "y".equalsIgnoreCase(answer); + System.out.println("Include description? [Enter 'n' for no]"); + boolean includeDescription = !matches("n", scanner); + + System.out.println("Write to file? [Enter 'y' for yes]"); + boolean writeToFile = matches("y", scanner); + scanner.close(); // Generate connections and output or write - PermissionNodesListCreater creater = new PermissionNodesListCreater(); - Set nodes = creater.gatherNodes(); - String output = StringUtils.join("\n", nodes); + String output = generatedOutput(includeDescription); if (writeToFile) { GeneratedFileWriter.createGeneratedFile(PERMISSIONS_TREE_FILE, output, CommentType.YML); @@ -34,4 +36,27 @@ public class PermissionsListWriter { } } + private static String generatedOutput(boolean includeDescription) { + PermissionNodesGatherer creater = new PermissionNodesGatherer(); + if (!includeDescription) { + Set nodes = creater.gatherNodes(); + return StringUtils.join("\n", nodes); + } + + Map permissions = creater.gatherNodesWithJavaDoc(); + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : permissions.entrySet()) { + sb.append(entry.getKey()) + .append(": ") + .append(entry.getValue()) + .append("\n"); + } + return sb.toString(); + } + + private static boolean matches(String answer, Scanner sc) { + String userInput = sc.nextLine(); + return answer.equalsIgnoreCase(userInput); + } + }