diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 079884ce..76c5ea26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,16 @@ jobs: with: name: java-${{matrix.version}} path: build/libs/* - license-header-check: + - name: Publish to local testing maven repo + run: ./gradlew publishAllPublicationsToTestingRepository + - name: Display directory structure of testing repo + run: ls -R build/testing-mvn-repo + - name: Save output from testing repo + uses: actions/upload-artifact@v2 + with: + name: java-${{matrix.version}}-testing-mvn-repo + path: build/testing-mvn-repo/* + linting-check: runs-on: ubuntu-latest container: image: jcxldn/openjdk-alpine:11-jdk @@ -39,8 +48,8 @@ jobs: - uses: actions/checkout@v2 - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Run the license formatter checker - run: ./gradlew licenseMain licenseTest + - name: Test our code against our spotless formatting options + run: ./gradlew spotlessCheck javadoc-check: runs-on: ubuntu-latest container: diff --git a/.gitignore b/.gitignore index 0290202d..848c5e82 100644 --- a/.gitignore +++ b/.gitignore @@ -52,4 +52,4 @@ bin *.code-workspace # Generated resources -src/main/resources/generated/* +common/src/main/resources/generated/* diff --git a/LICENSE_HEADER b/LICENSE_HEADER index 904e6a25..cd0f4bbc 100644 --- a/LICENSE_HEADER +++ b/LICENSE_HEADER @@ -1,2 +1,4 @@ -Copyright (c) 2020-${year} DumbDogDiner . All rights reserved. -Licensed under the MIT license, see LICENSE for more information... +/* + * Copyright (c) 2020-$YEAR DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ \ No newline at end of file diff --git a/build.gradle b/build.gradle index d50471d8..ce2da2bc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,181 +1,260 @@ plugins { - id 'java' - id 'maven-publish' - id 'jacoco' - id "io.freefair.lombok" version "5.3.0" - id "com.github.hierynomus.license" version "0.15.0" - // Nemerosa Versioning Plugin for the build info - id "net.nemerosa.versioning" version "2.14.0" + id "io.freefair.lombok" version "5.3.0" apply false + // spotless for license headers and linting + id "com.diffplug.spotless" version "5.11.0" apply false + // generation of project-wide javadocs + id "io.freefair.aggregate-javadoc" version "5.3.0" } -jacoco { +allprojects { + group = "com.dumbdogdiner" + version = "3.0.0" + + apply plugin: "java" + apply plugin: "jacoco" + + // Apply here instead of in plugins {} above to solve + // Maven publication [..] cannot include multiple components + // Solution: "I solved it. I put a publishing configuration into subprojects section, but applied plugin to a root project." + // Solution source: https://discuss.gradle.org/t/problem-with-publishing-with-maven-publish-in-a-multi-module-project/1695/2 + apply plugin: "maven-publish" + // Use JaCoCo 0.8.6 for (experimental) support for Java 15 class files. - toolVersion = "0.8.6" -} + jacoco { toolVersion = "0.8.6" } + + // Define Maven Central here so that jacoco can deps resolve properly + repositories { mavenCentral() } + + publishing { + repositories { + // Main publishing repo + maven { + name = "GitHubPackages" + url = uri("https://maven.pkg.github.com/DumbDogDiner/StickyAPI") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") + } + } + // Local testing maven repo + maven { + name = "Testing" + url = "${rootProject.projectDir}/build/testing-mvn-repo" + } + } + } -group = 'com.dumbdogdiner' + tasks.withType(Javadoc) { + /* + Javadoc Fixes, part 3 + Since JDK13 the javadoc html validator was changed, making it impossible to have javadocs + that are valid on both pre-13 and post-13 java versions. + The original workaround was suggested here: https://bugs.openjdk.java.net/browse/JDK-8223552 + However, this workaround does not work for us since we are using aggregate-javadoc. + So, we are using a workaround for the workaround from: + original: https://blog.joda.org/2014/02/turning-off-doclint-in-jdk-8-javadoc.html + archived: https://web.archive.org/web/20210117193942/https://blog.joda.org/2014/02/turning-off-doclint-in-jdk-8-javadoc.html + which, in turn, references this: https://github.com/GPars/GPars/blob/7cddf7cf2fec1fd66ef800edccfc03315d078a2b/build.gradle#L209 + */ + options.addBooleanOption("Xdoclint:-html", JavaVersion.current().isJava11Compatible()) -version = '2.1.0' + // Enable frames support if running on java 11 + options.addBooleanOption("-frames", JavaVersion.current().isJava11()) -// License Plugin Options -license { - header = project.file('LICENSE_HEADER') - ext.year = Calendar.getInstance().get(Calendar.YEAR) - mapping("java", "SLASHSTAR_STYLE") - exclude "**/*.json" // Exclude JSON to keep the font width data valid + // Include private and protected in the javadocs + options.memberLevel = JavadocMemberLevel.PRIVATE + } } -tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-XDignore.symbol.file" -} +subprojects { + apply plugin: "io.freefair.lombok" + apply plugin: "com.diffplug.spotless" -configurations { - jaxDoclet - // give test dependencies access to compileOnly dependencies to emulate providedCompile - testImplementation.extendsFrom compileOnly -} + // Spotless Options + spotless { + encoding 'UTF-8' // all formats will be interpreted as UTF-8 + java { + licenseHeaderFile(project.rootProject.file("LICENSE_HEADER")) + } + } -repositories { - mavenCentral() - jcenter() + tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-XDignore.symbol.file" + } - maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } - maven { url 'https://papermc.io/repo/repository/maven-public/' } + configurations { + jaxDoclet + // give test dependencies access to compileOnly dependencies to emulate providedCompile + testImplementation.extendsFrom compileOnly - // Define a Ivy repo for the font width data (that way we don't need another plugin!) - def ddd_mc_font = ivy { - url 'https://dumbdogdiner.github.io/' - patternLayout { artifact '/[module]/[revision]/[classifier].[ext]'} - metadataSources { artifact() } + dddResource // custom configuration for our ivy resources (eg. font info) + dddResource.description = "Resources (eg. yml or json data) to be included in jar builds" } - // Only use the Ivy repo for font width data - speeds up dependency resolution - exclusiveContent { - forRepositories(ddd_mc_font) - filter { includeGroup("dumbdogdiner") } + + repositories { + // Note: Maven Central is defined in allprojects + jcenter() + + maven { url "https://oss.sonatype.org/content/repositories/snapshots" } + maven { url "https://papermc.io/repo/repository/maven-public/" } + + // Note: Subprojects can't have repo overrides to we have to put it here + // Define a Ivy repo for the font width data (that way we don't need another plugin!) + def dddResources = ivy { + url "https://dumbdogdiner.github.io/" + patternLayout { artifact "/[module]/[revision]/[classifier].[ext]"} + metadataSources { artifact() } + } + // Only use the Ivy repo for font width data - speeds up dependency resolution + exclusiveContent { + forRepositories(dddResources) + filter { includeGroup("dumbdogdiner") } + } } -} -dependencies { - // Font width data (see above) - compile 'dumbdogdiner:mc-font-extractor:main:mojangles_width_data@json' + dependencies { + compileOnly "org.projectlombok:lombok:1.18.18" + annotationProcessor "org.projectlombok:lombok:1.18.18" - compileOnly 'org.projectlombok:lombok:1.18.18' - annotationProcessor 'org.projectlombok:lombok:1.18.18' + implementation "org.jetbrains:annotations:20.1.0" + implementation "io.github.classgraph:classgraph:4.8.104" + implementation "com.github.seancfoley:ipaddress:5.3.3" - compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT' - compileOnly 'net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT' - implementation 'org.jetbrains:annotations:20.1.0' - implementation 'com.google.code.gson:gson:2.8.6' - implementation 'io.github.classgraph:classgraph:4.8.102' - implementation 'com.github.seancfoley:ipaddress:5.3.3' - - // Tests - JUnit 5 - testImplementation("org.junit.jupiter:junit-jupiter-params:5.7.1") - testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.1") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.1") + // Tests - JUnit 5 + testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.1" + testImplementation "org.junit.jupiter:junit-jupiter-api:5.7.1" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.7.1" - // Tests - Mocking Suite (eg. mocking Bukkit for tests) - testImplementation("org.mockito:mockito-core:3.7.7") -} + // Tests - Mocking Suite (eg. mocking Bukkit for tests) + testImplementation "org.mockito:mockito-core:3.7.7" + } -test { - useJUnitPlatform() - testLogging { - events "passed", "skipped", "failed" - // Show System.out for code ran by tests - showStandardStreams = true - } - finalizedBy jacocoTestReport // report is always generated after tests run -} + test { + useJUnitPlatform() + testLogging { + events "passed", "skipped", "failed" + // Show System.out for code ran by tests + showStandardStreams = true + } + finalizedBy jacocoTestReport // report is always generated after tests run + } -jacocoTestReport { - dependsOn test // tests are required to run before generating the report - reports { - xml.enabled true - html.enabled true + jacocoTestReport { + dependsOn test // tests are required to run before generating the report + reports { + xml.enabled true + html.enabled true + } + } + + task sources(type: Jar, dependsOn: classes) { + archiveClassifier.set("sources") + from sourceSets.main.allSource + } + + + // Javadoc Fixes + // Some environments (such as the builder image) do not use UTF-8 as the default encoding! + // This sets UTF-8 as the encoding for the following tasks: delombok, compileJava, compileTestJava and javadoc. + delombok.encoding = "UTF-8" + compileJava.options.encoding = "UTF-8" + compileTestJava.options.encoding = "UTF-8" + javadoc.options.encoding = "UTF-8" + + + // Run the linter before compiling the source code. + tasks.compileJava.dependsOn spotlessApply + tasks.build.dependsOn sources + + // Per-module publishing (eg. stickyapi-common) + if (project.name != "serverversion") { // Ignore :common:serverversion (already included in :common) + publishing { + publications { + gprSubprojects(MavenPublication) { + artifactId "${rootProject.name}-${project.name}" + println("[debug] ${project.name} found component: " + components.java) + + from(components.java) + artifact sources // Publish the output of the sources task + } + } + } } } -task sources(type: Jar, dependsOn: classes) { +// Root build: create uber jar from subproject outputs +jar { from subprojects.sourceSets.main.output } + +// Root build: create uber sources from subproject sources +task rootSources(type: Jar, dependsOn: classes) { archiveClassifier.set("sources") - from sourceSets.main.allSource + // Use source code from all subprojects for sources. + // TODO: Use certain subprojects only to allow for multiple jar outputs + from subprojects.sourceSets.main.allSource } +// Generate a combined test report for passing/failing tests project-wide +// src: https://stackoverflow.com/a/16921750 +task rootTestReport(type: TestReport) { + destinationDir = file("$buildDir/reports/allTests") + // Include the results from the `test` task in all subprojects + reportOn subprojects*.test +} -// Javadoc Fixes -// Some environments (such as the builder image) do not use UTF-8 as the default encoding! -// This sets UTF-8 as the encoding for the following tasks: delombok, compileJava, compileTestJava and javadoc. -delombok.encoding = "UTF-8" -compileJava.options.encoding = "UTF-8" -compileTestJava.options.encoding = "UTF-8" -javadoc.options.encoding = "UTF-8" - - -// Build Info -// Set the timestamp format -def dataBuildTimestamp = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" - -// Import the filter -import org.apache.tools.ant.filters.ReplaceTokens - -// Define the map containing the tokens we want to replace -def tokensMap = [ - BUILDINFO_VERSION: project.version, - BUILDINFO_DATEFORMAT: dataBuildTimestamp, - BUILDINFO_TIMESTAMP: new java.text.SimpleDateFormat(dataBuildTimestamp).format(new Date()), - BUILDINFO_COMMIT: versioning.info.commit, - BUILDINFO_BRANCH: versioning.info.branch, - BUILDINFO_ISDIRTY: versioning.info.dirty.toString() - ] - -// Create task to replace the tokens with their actual values -// NOTE: At the moment this replaces tokens *globally* (format eg. @BUILDINFO_COMMIT@ in source code) -task processSourceTokens(type: Sync) { - from sourceSets.main.java - into 'build/processed/src/main/java' - filter(ReplaceTokens, tokens: tokensMap) - - // Pretty print the build info - println("\n----- StickyAPI Build Info -----\n") - tokensMap.each { println "${String.format("%1\$-" + 10 + "s", it.key.replace("BUILDINFO_", "").toLowerCase())}\t${it.value}" } +// Generate an additional jacoco report project-wide +// src: https://github.com/gradle/gradle/issues/10708#issuecomment-566279825 +task rootJacocoMergedReport(type: JacocoReport) { + //dependsOn = subprojects.test + additionalSourceDirs.setFrom files(subprojects.sourceSets.main.allSource.srcDirs) + sourceDirectories.setFrom files(subprojects.sourceSets.main.allSource.srcDirs) + classDirectories.setFrom files(subprojects.sourceSets.main.output) + executionData.setFrom project.fileTree(dir: ".", include: "**/build/jacoco/test.exec") + reports { + xml.enabled true + html.enabled true + } } -// Use the filter task as the input for compileJava -compileJava.source = processSourceTokens.outputs - -// Font Width Info -task copyMCFontExtractor(type: Copy) { - def path = project.configurations.compile.find {it.name.startsWith("mc-font-extractor") } - println path - from file(path) - // into file("src/main/resources") - // - Please keep this comment for future reference. - // - This is how we would do this if we weren't also adding build info (see processSourceTokens) - destinationDir file("src/main/resources/generated/") - rename 'mc-font-extractor-main-mojangles_width_data.json', 'mojangles_width_data.json' + +// Create a libs/modules folder with submodule jars +task copySubprojectJars(type: Copy, dependsOn: subprojects.jar) { + // Copy subproject jar and sources + from(subprojects.jar) + from(subprojects.sources) + into rootProject.file("build/libs/modules") } +// Root build: run copySubprojectJars after build +tasks.build.finalizedBy copySubprojectJars -// Run the license formatter and font data copier before compiling the source code. -tasks.compileJava.dependsOn licenseFormatMain, licenseFormatTest, copyMCFontExtractor -tasks.build.dependsOn sources -tasks.publish.dependsOn build +// Root build: run rootSources during build +tasks.build.dependsOn rootSources +// Root build: generate project wide test, coverage and javadoc results +tasks.test.finalizedBy rootTestReport, rootJacocoMergedReport, javadoc -publishing { - repositories { - maven { - name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/DumbDogDiner/StickyAPI") - credentials { - username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR") - password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN") - } - } +// Root build: also run aggregateJavadoc after javadoc to generate project-wide javadocs +tasks.javadoc.finalizedBy aggregateJavadoc + +// Javadoc fixes (pt. 2, see above entries) +aggregateJavadoc.options.encoding = "UTF-8" + +task browseJavadoc { + dependsOn javadoc + description "Browse javadoc" + group = "documentation" + doLast { + java.awt.Desktop.desktop.browse new URI(("file:///" << System.getProperty("user.dir").replace('\\','/') << "/build/docs/javadoc/index.html").toString()) } +} + +tasks.publish.dependsOn build + +publishing { + // Uber-jar publication publications { - gpr(MavenPublication) { + gprRoot(MavenPublication) { from(components.java) - artifact sources // Publish the output of the sources task + artifact rootSources // Publish the output of the (root) sources task } } } diff --git a/bukkit/build.gradle b/bukkit/build.gradle new file mode 100644 index 00000000..b93cda29 --- /dev/null +++ b/bukkit/build.gradle @@ -0,0 +1,12 @@ +dependencies { + implementation project(":common") + testImplementation project(":common").sourceSets.test.output + + compileOnly "com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT" + + // Fun fact: paper/spigot/etc doesn't include netty! (as it's from NMS) + // So instead let's use the netty version that we were using before (inherited from bungeecord) + compileOnly "io.netty:netty-codec:4.1.58.Final" + + testImplementation "com.google.code.gson:gson:2.8.6" +} diff --git a/bukkit/lombok.config b/bukkit/lombok.config new file mode 100644 index 00000000..189c0bef --- /dev/null +++ b/bukkit/lombok.config @@ -0,0 +1,3 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/AsyncCommand.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/AsyncCommand.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/AsyncCommand.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/AsyncCommand.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/BukkitCommandBuilder.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/BukkitCommandBuilder.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/BukkitCommandBuilder.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/BukkitCommandBuilder.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/ExitCode.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/ExitCode.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/ExitCode.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/ExitCode.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/PluginCommand.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/PluginCommand.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/PluginCommand.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/PluginCommand.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/package-info.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/package-info.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/command/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/VoidGenerator.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/package-info.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/package-info.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/generator/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/ClickableSlot.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/ClickableSlot.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/ClickableSlot.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/ClickableSlot.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/GUI.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/GUI.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/GUI.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/GUI.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/GUISlot.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/GUISlot.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/GUISlot.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/GUISlot.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/package-info.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/package-info.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/gui/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/BookAndQuillBuilder.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilder.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java similarity index 95% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java index 1f5149b8..e726c842 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java +++ b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/item/package-info.java @@ -4,6 +4,7 @@ */ /** * Classes related to item generation or manipulation + * @since 3.0 */ package com.dumbdogdiner.stickyapi.bukkit.item; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/BukkitHandler.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/BukkitHandler.java similarity index 98% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/BukkitHandler.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/BukkitHandler.java index ef215037..9d066204 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/BukkitHandler.java +++ b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/BukkitHandler.java @@ -13,6 +13,11 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; + +/** + * @deprecated This will be superseded and removed in a future release. + */ +@Deprecated public class BukkitHandler { private BukkitHandler() { } diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/PacketInjector.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/PacketInjector.java similarity index 94% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/PacketInjector.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/PacketInjector.java index 7dda763b..bc5cddf6 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/PacketInjector.java +++ b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/nms/PacketInjector.java @@ -12,9 +12,16 @@ /** * Handles Packet Injection + * + * @deprecated This will be superseded and removed in a future release. */ +@Deprecated public class PacketInjector { + /** + * @deprecated This will be superseded and removed in a future release. + */ + @Deprecated public interface InjectionService { /** *

diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/package-info.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/package-info.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Orientation.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Orientation.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Orientation.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Orientation.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Parametric.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Parametric.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Parametric.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Parametric.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/ParticleSystem.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/ParticleSystem.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/ParticleSystem.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/ParticleSystem.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Shape.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Shape.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Shape.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/Shape.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/shapes/Circle.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/shapes/Circle.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/shapes/Circle.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/particle/shapes/Circle.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/player/PlayerSnapshot.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/player/PlayerSnapshot.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/player/PlayerSnapshot.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/player/PlayerSnapshot.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/player/package-info.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/player/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/player/package-info.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/player/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/PlayerSelector.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/PlayerSelector.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/PlayerSelector.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/PlayerSelector.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/ServerUtil.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/ServerUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/ServerUtil.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/ServerUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/SoundUtil.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/SoundUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/SoundUtil.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/SoundUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java similarity index 69% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java index beb5505b..90673420 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java +++ b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java @@ -5,9 +5,12 @@ package com.dumbdogdiner.stickyapi.bukkit.util; import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; import javax.annotation.Nullable; +import com.dumbdogdiner.stickyapi.common.config.providers.YamlProvider; import com.dumbdogdiner.stickyapi.common.translation.LocaleProvider; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -60,9 +63,23 @@ public static LocaleProvider setupLocale(@NotNull JavaPlugin plugin, @Nullable L if (!localeEnabled) { plugin.getLogger() .severe("Failed to configure default locale file - perhaps you deleted it? Will create a new one."); - // FIXME: This is horrible and needs to be improved try { - localeProvider.writeLocaleStream(plugin.getResource("messages.en_us.yml"), "messages.en_us.yml", true); + // Step 1: Make sure the locale file exists (returns null if not found) + InputStream localeFile = plugin.getResource("messages.en_us.yml"); + + // Step 1.5: Throw an exception if the file doesn't exist + if (localeFile == null) + throw new FileNotFoundException("The locale file was not found in our embedded resources!"); + + // Step 2: Load the yml from plugin.getResource (the internal .jar resource) + YamlProvider embeddedMessagesResource = new YamlProvider(plugin.getResource("messages.en_us.yml")); + + // Step 3: Create a File instance representing our output dir in the plugin's data folder + File outputLocation = new File(localeProvider.getLocaleFolder(), "messages.en_us.yml"); + // outputLocation should now be something like [..]/plugins/[..]/locale/messages.en_us.yml + + // Step 4: write the embedded messages resource to the plugin data dir + embeddedMessagesResource.save(outputLocation); } catch (Exception e) { e.printStackTrace(); plugin.getLogger().severe("Something went horribly wrong while saving the default locale."); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/package-info.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/package-info.java rename to bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/package-info.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java b/bukkit/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java rename to bukkit/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/BookBuilderTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java b/bukkit/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java rename to bukkit/src/test/java/com/dumbdogdiner/stickyapi/bukkit/item/WrittenBookBuilderTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/particle/OrientationTest.java b/bukkit/src/test/java/com/dumbdogdiner/stickyapi/bukkit/particle/OrientationTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/bukkit/particle/OrientationTest.java rename to bukkit/src/test/java/com/dumbdogdiner/stickyapi/bukkit/particle/OrientationTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bukkit/util/ServerUtilTest.java b/bukkit/src/test/java/com/dumbdogdiner/stickyapi/bukkit/util/ServerUtilTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/bukkit/util/ServerUtilTest.java rename to bukkit/src/test/java/com/dumbdogdiner/stickyapi/bukkit/util/ServerUtilTest.java diff --git a/src/test/resources/book1.json b/bukkit/src/test/resources/book1.json similarity index 100% rename from src/test/resources/book1.json rename to bukkit/src/test/resources/book1.json diff --git a/src/test/resources/rulebook.json b/bukkit/src/test/resources/rulebook.json similarity index 100% rename from src/test/resources/rulebook.json rename to bukkit/src/test/resources/rulebook.json diff --git a/src/test/resources/rulebook.md b/bukkit/src/test/resources/rulebook.md similarity index 100% rename from src/test/resources/rulebook.md rename to bukkit/src/test/resources/rulebook.md diff --git a/bungee/build.gradle b/bungee/build.gradle new file mode 100644 index 00000000..87a2b2eb --- /dev/null +++ b/bungee/build.gradle @@ -0,0 +1,6 @@ +dependencies { + implementation project(":common") + testImplementation project(":common").sourceSets.test.output + + compileOnly "net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT" +} diff --git a/bungee/lombok.config b/bungee/lombok.config new file mode 100644 index 00000000..189c0bef --- /dev/null +++ b/bungee/lombok.config @@ -0,0 +1,3 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/command/BungeeCommandBuilder.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/command/BungeeCommandBuilder.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bungeecord/command/BungeeCommandBuilder.java rename to bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/command/BungeeCommandBuilder.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/PacketRegistration.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/PacketRegistration.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/PacketRegistration.java rename to bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/PacketRegistration.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/SoundPacket.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/SoundPacket.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/SoundPacket.java rename to bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/packet/SoundPacket.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/protocol/Protocol.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/protocol/Protocol.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bungeecord/protocol/Protocol.java rename to bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/protocol/Protocol.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/protocol/ProtocolConstants.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/protocol/ProtocolConstants.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bungeecord/protocol/ProtocolConstants.java rename to bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/protocol/ProtocolConstants.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/Sound.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/Sound.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/Sound.java rename to bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/Sound.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundUtil.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundUtil.java rename to bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java similarity index 72% rename from src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java rename to bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java index 89c50c7e..1e782b2c 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java +++ b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java @@ -5,8 +5,11 @@ package com.dumbdogdiner.stickyapi.bungeecord.util; import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; import com.dumbdogdiner.stickyapi.annotation.Untested; +import com.dumbdogdiner.stickyapi.common.config.providers.YamlProvider; import com.dumbdogdiner.stickyapi.common.translation.LocaleProvider; import org.jetbrains.annotations.NotNull; @@ -67,10 +70,23 @@ public static LocaleProvider setupLocale(@NotNull Plugin plugin, @Nullable Local if (!localeEnabled) { plugin.getLogger() .severe("Failed to configure default locale file - perhaps you deleted it? Will create a new one."); - // FIXME: This is horrible and needs to be improved try { - localeProvider.writeLocaleStream(plugin.getResourceAsStream("messages.en_us.yml"), "messages.en_us.yml", - true); + // Step 1: Make sure the locale file exists (returns null if not found) + InputStream localeFile = plugin.getResourceAsStream("messages.en_us.yml"); + + // Step 1.5: Throw an exception if the file doesn't exist + if (localeFile == null) + throw new FileNotFoundException("The locale file was not found in our embedded resources!"); + + // Step 2:Load the yml from plugin.getResource (the internal .jar resource) + YamlProvider embeddedMessagesResource = new YamlProvider(plugin.getResourceAsStream("messages.en_us.yml")); + + // Step 3: Create a File instance representing our output dir in the plugin's data folder + File outputLocation = new File(localeProvider.getLocaleFolder(), "messages.en_us.yml"); + // outputLocation should now be something like [..]/plugins/[..]/locale/messages.en_us.yml + + // Step 4: write the embedded messages resource to the plugin data dir + embeddedMessagesResource.save(outputLocation); } catch (Exception e) { e.printStackTrace(); plugin.getLogger().severe("Something went horribly wrong while saving the default locale."); diff --git a/src/test/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundTest.java b/bungee/src/test/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundTest.java rename to bungee/src/test/java/com/dumbdogdiner/stickyapi/bungeecord/util/SoundTest.java diff --git a/common/build.gradle b/common/build.gradle new file mode 100644 index 00000000..5e10565b --- /dev/null +++ b/common/build.gradle @@ -0,0 +1,121 @@ +plugins { + // Nemerosa Versioning Plugin for the build info + id "net.nemerosa.versioning" version "2.14.0" + + // for "api" in dependencies { } + id "java-library" +} + +dependencies { + // Depend on serverversion proj + api project(":common:serverversion") // expose serverversion when implementing :common + testImplementation project(":common:serverversion").sourceSets.test.output + + // Depend on the config project + api project(":config") // expose config when implementing :common + testImplementation project(":config").sourceSets.test.output + + // LocaleProviderTest - add snakeyaml so YamlProvider (from the :config project) can work properly + // testRuntimeOnly = only accessible during the test job + testRuntimeOnly "org.yaml:snakeyaml:1.27" + + // Font width data (see above) + dddResource "dumbdogdiner:mc-font-extractor:main:mojangles_width_data@json" + + implementation "com.google.code.gson:gson:2.8.6" + + // Dependencies available in both bukkit and bungee + compileOnly "net.md-5:bungeecord-chat:1.16-R0.5-SNAPSHOT" + + // Only included in paper? (ShortID.java) + compileOnly "commons-lang:commons-lang:2.6" +} + +/* + Build Info + ---------- + The following lines (and the processSourceTokens task) serve to embed build information + such as versions, timestamps, commit details, as well as branch and working tree status + into StickyAPI during build-time. + + When using StickyAPI, these values can be retrieved from their respective getters at + com.dumbdogdiner.stickyapi.Stickyapi + + ---------- + + The processSourceTokens task will also print out a list of all the tokens to be added + to the build, for debugging reasons (eg. to ensure the info is correct) + + These is also an accompanying test at (test src) com.dumbdogdiner.stickyapi.StickyAPITest + */ + +// Set the timestamp format +def dataBuildTimestamp = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" + +// Import the filter +import org.apache.tools.ant.filters.ReplaceTokens + +// Define the map containing the tokens we want to replace +def tokensMap = [ + BUILDINFO_VERSION: project.rootProject.version, + BUILDINFO_DATEFORMAT: dataBuildTimestamp, + BUILDINFO_TIMESTAMP: new java.text.SimpleDateFormat(dataBuildTimestamp).format(new Date()), + BUILDINFO_COMMIT: versioning.info.commit, + BUILDINFO_BRANCH: versioning.info.branch, + BUILDINFO_ISDIRTY: versioning.info.dirty.toString() + ] + +// Create task to replace the tokens with their actual values +// NOTE: At the moment this replaces tokens *globally* (format eg. @BUILDINFO_COMMIT@ in source code) +task processSourceTokens(type: Sync) { + from sourceSets.main.java + into "build/processed/src/main/java" + filter(ReplaceTokens, tokens: tokensMap) + + // Pretty print the build info + println("\n----- (Common) StickyAPI Build Info -----\n") + tokensMap.each { println "${String.format("%1\$-" + 10 + "s", it.key.replace("BUILDINFO_", "").toLowerCase())}\t${it.value}" } +} +// Use the filter task as the input for compileJava +compileJava.source = processSourceTokens.outputs + + +/* + Font Width Info + ---------- + This task serves to copy width data from the default Minecraft font into the final jar. + This data is generated by . + */ + +// Font Width Info +task copyMCFontExtractor(type: Copy) { + def path = project.configurations.dddResource.find {it.name.startsWith("mc-font-extractor") } + println("common: Found font data at: " + path) + from file(path) + // into file("src/main/resources") + // - Please keep this comment for future reference. + // - This is how we would do this if we weren't also adding build info (see processSourceTokens, above comments) + destinationDir file("src/main/resources/generated/") + rename "mc-font-extractor-main-mojangles_width_data.json", "mojangles_width_data.json" +} + +// Run the font data copier before compiling the source code. +tasks.compileJava.dependsOn copyMCFontExtractor + + +// Common build: create a jar from the :common & :common:serverversion projects +jar { + from sourceSets.main.output + from project(":common:serverversion").sourceSets.main.output +} + +// Common build: create uber sources from subproject sources +task commonSources(type: Jar, dependsOn: classes) { + archiveClassifier.set("sources") + // Use source code from :common & :common:serverversion projects + from sourceSets.main.allSource + from project(":common:serverversion").sourceSets.main.allSource +} + +// Common build: override the usual sources output with our one containing ServerVersion +tasks.sources.finalizedBy commonSources diff --git a/common/lombok.config b/common/lombok.config new file mode 100644 index 00000000..189c0bef --- /dev/null +++ b/common/lombok.config @@ -0,0 +1,3 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true diff --git a/common/serverversion/build.gradle b/common/serverversion/build.gradle new file mode 100644 index 00000000..abff66bb --- /dev/null +++ b/common/serverversion/build.gradle @@ -0,0 +1,4 @@ +dependencies { + compileOnly "net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT" + compileOnly "com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT" +} diff --git a/common/serverversion/lombok.config b/common/serverversion/lombok.config new file mode 100644 index 00000000..189c0bef --- /dev/null +++ b/common/serverversion/lombok.config @@ -0,0 +1,3 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java b/common/serverversion/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java rename to common/serverversion/src/main/java/com/dumbdogdiner/stickyapi/common/ServerVersion.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/ServerVersionTest.java b/common/serverversion/src/test/java/com/dumbdogdiner/stickyapi/common/ServerVersionTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/ServerVersionTest.java rename to common/serverversion/src/test/java/com/dumbdogdiner/stickyapi/common/ServerVersionTest.java diff --git a/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/common/serverversion/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker similarity index 100% rename from src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker rename to common/serverversion/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java b/common/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java similarity index 96% rename from src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java index a61fbc5a..c4d33844 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/StickyAPI.java @@ -36,7 +36,7 @@ private StickyAPI() { /** * Get the current version of API. * - * @since TBA + * @since 3.0 * @return {@link String} version * */ @@ -52,7 +52,7 @@ private StickyAPI() { /** * Get a string with the latest commit (id) at API's build-time. * - * @since TBA + * @since 3.0 * @return {@link String} commit id */ @Getter @@ -61,7 +61,7 @@ private StickyAPI() { /** * Get a string with the current branch at API's build-time. * - * @since TBA + * @since 3.0 * @return {@link String} branch name */ @Getter @@ -74,7 +74,7 @@ private StickyAPI() { /** * Get a Date object showing the current time at API's build-time. * - * @since TBA + * @since 3.0 * @return {@link Date} date */ public static Date getTimestamp() { @@ -91,7 +91,7 @@ public static Date getTimestamp() { /** * Get a string with the latest commit sha at API's build-time. * - * @since TBA + * @since 3.0 * @return {@link String} sha */ public static String getSha() { @@ -103,7 +103,7 @@ public static String getSha() { *

* If the working directory was dirty, this will return true, meaning there were modified tracked files and staged changes at build-time. * - * @since TBA + * @since 3.0 * @return {@link Boolean} isDirty */ public static Boolean getIsDirty() { diff --git a/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java b/common/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/annotation/Untested.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/arguments/Arguments.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/arguments/Arguments.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/arguments/Arguments.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/arguments/Arguments.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/arguments/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/arguments/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/arguments/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/arguments/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/cache/Cache.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/cache/Cache.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/cache/Cache.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/cache/Cache.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/cache/Cacheable.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/cache/Cacheable.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/cache/Cacheable.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/cache/Cacheable.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/cache/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/cache/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/cache/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/cache/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/chat/ChatMessage.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/chat/ChatMessage.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/chat/ChatMessage.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/chat/ChatMessage.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/command/CommandBuilder.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/command/CommandBuilder.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/command/CommandBuilder.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/command/CommandBuilder.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/command/ExitCode.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/command/ExitCode.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/command/ExitCode.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/command/ExitCode.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTag.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTag.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTag.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTag.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtCompoundTag.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonAdapter.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonAdapter.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonAdapter.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonAdapter.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonTag.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonTag.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonTag.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtJsonTag.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtListTag.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtListTag.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtListTag.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtListTag.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTag.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTag.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTag.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTag.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtPrimitiveTag.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtPrimitiveTag.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtPrimitiveTag.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtPrimitiveTag.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTag.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTag.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTag.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtStringTag.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtTag.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtTag.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtTag.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/NbtTag.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java similarity index 95% rename from src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java index 1e9b20c9..2ac1efec 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/nbt/package-info.java @@ -4,6 +4,7 @@ */ /** * This package contains classes designed to help work with SNBT + * @since 3.0 */ package com.dumbdogdiner.stickyapi.common.nbt; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/scheduler/Scheduler.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/scheduler/Scheduler.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/scheduler/Scheduler.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/scheduler/Scheduler.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/scheduler/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/scheduler/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/scheduler/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/scheduler/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java similarity index 83% rename from src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java index 38e5ff40..2cff6dad 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java @@ -6,8 +6,8 @@ import java.io.File; -import com.dumbdogdiner.stickyapi.common.configuration.file.FileConfiguration; -import com.dumbdogdiner.stickyapi.common.configuration.file.YamlConfiguration; +import com.dumbdogdiner.stickyapi.common.config.FileConfiguration; +import com.dumbdogdiner.stickyapi.common.config.providers.YamlProvider; import com.dumbdogdiner.stickyapi.common.util.Debugger; import org.jetbrains.annotations.NotNull; @@ -27,7 +27,7 @@ public class Locale { File localeFile; @Getter - FileConfiguration localeConfig = new YamlConfiguration(); + FileConfiguration localeConfig; /** * Create a new locale object @@ -39,7 +39,7 @@ public class Locale { public Locale(@NotNull File localeFile) { this.localeFile = localeFile; try { - localeConfig.load(this.localeFile); + localeConfig = new YamlProvider(localeFile); isValid = true; } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java similarity index 83% rename from src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java index 22d062ab..cb1db7fd 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java @@ -5,10 +5,6 @@ package com.dumbdogdiner.stickyapi.common.translation; import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.FileOutputStream; -import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; import java.util.Map; import java.util.TreeMap; @@ -258,49 +254,6 @@ public boolean setDefaultLocale(@NotNull String name) { return true; } - /** - * Save an internal resource to the data file. - * - * @param in File inputstream - * @param resourcePath The path to which the resource should be saved - * @param replace Whether or not to replace the file if it already exists - * @throws IllegalArgumentException - * @throws IOException - */ - public void writeLocaleStream(@NotNull InputStream in, @NotNull String resourcePath, @NotNull boolean replace) - throws IllegalArgumentException, IOException { - if (resourcePath == null || resourcePath.equals("")) { - throw new IllegalArgumentException("Resource path cannot be null or empty"); - } - - resourcePath = resourcePath.replace('\\', '/'); - if (in == null) { - throw new IllegalArgumentException("The embedded resource '" + resourcePath + "' cannot be found"); - } - - File outFile = new File(localeFolder, resourcePath); - int lastIndex = resourcePath.lastIndexOf('/'); - File outDir = new File(localeFolder, resourcePath.substring(0, lastIndex >= 0 ? lastIndex : 0)); - - if (!outDir.exists()) { - outDir.mkdirs(); - } - - if (outFile.exists() && !replace) { - System.out.println("resource already exists"); - return; - } - - OutputStream out = new FileOutputStream(outFile); - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - out.close(); - in.close(); - } - /** * Checks if a locale with the given name is loaded. Throws * `IllegalArgumentException` if not found. diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Translation.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Translation.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/translation/Translation.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Translation.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/translation/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/translation/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/Debugger.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/Debugger.java similarity index 98% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/Debugger.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/Debugger.java index b865be47..946db381 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/Debugger.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/Debugger.java @@ -7,9 +7,8 @@ import java.util.Random; import java.util.logging.Logger; -import javax.annotation.Nullable; - import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import lombok.Setter; import lombok.Getter; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/IPUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java similarity index 99% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java index f65d3b7f..b20c6cb3 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/MathUtil.java @@ -164,6 +164,7 @@ public static boolean inRange(int number, int min, int max) { /** * @see #randomElement(List) + * @since 3.0 */ public static char randomElement(char @NotNull [] choices) { return Objects.requireNonNull(randomElement(Chars.asList(choices))); @@ -171,6 +172,7 @@ public static char randomElement(char @NotNull [] choices) { /** * @see #randomElement(List) + * @since 3.0 */ public static int randomElement(int @NotNull [] choices) { return Objects.requireNonNull(randomElement(Ints.asList(choices))); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NotificationType.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/NotificationType.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/NotificationType.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/NotificationType.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/NumberUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/Paginator.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/Paginator.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/Paginator.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/Paginator.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/ShortID.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java similarity index 99% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java index b289e5c5..6e5922ce 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/StringUtil.java @@ -278,6 +278,7 @@ public static boolean startsWithIgnoreCase(@NotNull final String string, @NotNul * @param prefix Prefix of string to compare * @return {@link Boolean} * @throws NullPointerException if prefix or string is null + * @since 3.0 */ public static boolean startsWith(@NotNull final String string, @NotNull final String prefix) { if (string.length() < prefix.length()) { @@ -315,6 +316,7 @@ public static UUID hyphenateUUID(@NotNull String uuid) { * @param minRunBeforeSpace Minimum number of characters before a space can * appear, set to 0 to disable space * @return A string of random characters, where the length + * @since 3.0 */ public static String randomObfuscatedString(int min, int max, int minRunBeforeSpace) { Preconditions.checkArgument(max >= min, "Max cannot be less than min"); @@ -362,6 +364,7 @@ public static String randomObfuscatedString(int min, int max, int minRunBeforeSp * @param input The input string * @return A string where the relevant ampersands are replaced with section * symbols + * @since 3.0 */ public static String formatChatCodes(String input) { return input.replaceAll("&(?=([a-f]|[0-9]|[klmnor]))", Character.toString(ChatColor.COLOR_CHAR)); diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java similarity index 99% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java index 2409e091..1ca0d78a 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/TextUtil.java @@ -22,7 +22,7 @@ /** * Utilities for text, such as in chat, books, and signs * - * @since TBA (rewritten) + * @since 3.0 (rewrite) */ public class TextUtil { private TextUtil() { diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java similarity index 99% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java index b729daa8..a13faa49 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/TimeUtil.java @@ -12,9 +12,8 @@ import java.util.List; import java.util.Optional; -import javax.annotation.Nullable; - import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Utility methods for dealing with time and duration parsing. diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/FieldUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/FieldUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/FieldUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/FieldUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/UnsafeUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/reflection/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLPair.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLPair.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLPair.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLPair.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/URLUtil.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/common/util/url/package-info.java diff --git a/src/main/java/com/dumbdogdiner/stickyapi/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/package-info.java similarity index 100% rename from src/main/java/com/dumbdogdiner/stickyapi/package-info.java rename to common/src/main/java/com/dumbdogdiner/stickyapi/package-info.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/StickyAPITest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/StickyAPITest.java similarity index 86% rename from src/test/java/com/dumbdogdiner/stickyapi/StickyAPITest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/StickyAPITest.java index 660cfaa4..abe7cccb 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/StickyAPITest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/StickyAPITest.java @@ -4,10 +4,10 @@ */ package com.dumbdogdiner.stickyapi; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/command/ExitCodeTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/command/ExitCodeTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/command/ExitCodeTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/command/ExitCodeTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java similarity index 90% rename from src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java index ca58e4de..a5ba5e99 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtBooleanTagTest.java @@ -4,16 +4,12 @@ */ package com.dumbdogdiner.stickyapi.common.nbt; +import static org.junit.jupiter.api.Assertions.assertEquals; + import com.google.gson.JsonPrimitive; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - - -import static org.junit.jupiter.api.Assertions.*; -@RunWith(Parameterized.class) class NbtBooleanTagTest { @ParameterizedTest diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTagTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTagTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTagTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/nbt/NbtNumberTagTest.java diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java new file mode 100644 index 00000000..cb8948c9 --- /dev/null +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.translation; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; + +import com.dumbdogdiner.stickyapi.common.util.Debugger; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +@TestInstance(Lifecycle.PER_CLASS) +@TestMethodOrder(OrderAnnotation.class) +public class LocaleProviderTest { + + private static final File localeDirectoryGroup1 = new File("src/test/resources/localeprovider/group1"); + + private static final File nonExistentDirectory = new File("build/localeprovider-newfolder"); + + private LocaleProvider localeProviderGroup1; + + // Used for tests 2/3 + private ConcurrentHashMap loadedLocales; + + private enum Values { + NETWORK_NAME + } + + @BeforeAll + public void setup() { + // Enable the StickyAPI debugger + Debugger.setEnabled(true); + + // Create locale providers + localeProviderGroup1 = new LocaleProvider(localeDirectoryGroup1); + + // Delete the non-existent testing directory if it exists + if (nonExistentDirectory.exists()) { + assertTrue(nonExistentDirectory.delete()); // Attempt to delete the directory + } + } + + @Test + @Order(1) + public void testLoadLocaleString() { + assertTrue(localeProviderGroup1.loadLocale("messages.en_us.yml")); + } + + @Test + @Order(2) + public void testLoadedLocalesSizeOneLoaded() { + loadedLocales = localeProviderGroup1.getLoadedLocales(); + assertEquals(1, loadedLocales.size()); + } + + @Test + @Order(3) + public void testLoadedLocalesContentOneLoaded() { + Locale onlyLocale = (Locale) loadedLocales.values().toArray()[0]; + assertEquals(localeProviderGroup1.getLocale("messages.en_us"), onlyLocale); + } + + @Test + @Order(4) + public void testGetDefaultLocaleNull() { + assertEquals(null, localeProviderGroup1.getDefaultLocale()); + } + + @Test + @Order(5) + public void testSetDefaultLocaleLoaded() { + assertTrue(localeProviderGroup1.setDefaultLocale("messages.en_us")); + } + + @Test + @Order(6) + public void testSetDefaultLocaleNotLoaded() { + assertFalse(localeProviderGroup1.setDefaultLocale("not-loaded-locale")); + } + + @Test + @Order(7) + public void testGetDefaultLocale() { + assertEquals(localeProviderGroup1.getLocale("messages.en_us"), localeProviderGroup1.getDefaultLocale()); + } + + @Test + @Order(8) + public void testLoadLocaleSameOneTwiceWithExtension() { + // Should return false and debug "already loaded" + assertFalse(localeProviderGroup1.loadLocale("messages.en_us.yml")); + } + + @Test + @Order(9) + public void testLoadLocaleSameOneTwiceNoExtension() { + // Should return false and debug "already loaded" + assertFalse(localeProviderGroup1.loadLocale("messages.en_us")); + } + + @Test + @Order(10) + public void testLoadLocaleNonExistentFile() { + // Should return false and debug "could not find file" + assertFalse(localeProviderGroup1.loadLocale("non-existent-locale.yml")); + } + + @Test + @Order(11) + public void testTranslate() { + String output = localeProviderGroup1.translate("player-has-not-joined", new HashMap() {{ + put("prefix", "Msg>"); + put("target", "Notch"); + }}); + + // Translate changes & to § for ChatColor codes + assertEquals("Msg>§cError! The player Notch has not joined before!", output); + } + + @Test + @Order(12) + public void testTranslateNonExistentNode() { + // should return null and debug "node does not exist" + assertNull(localeProviderGroup1.translate("non-existent", new HashMap<>())); + } + + @Test + @Order(13) + public void testTranslateEmptyNode() { + // should return null and debug "invalid node name" + assertNull(localeProviderGroup1.translate("", new HashMap<>())); + } + + @Test + @Order(14) + public void testTranslateNullNode() { + // should return null and debug "invalid node name" + assertNull(localeProviderGroup1.translate(null, new HashMap<>())); + } + + @Test + @Order(15) + public void testTranslateNoColor() { + String output = localeProviderGroup1.translateNoColor("player-has-not-joined", new HashMap() {{ + put("prefix", "Msg>"); + put("target", "Notch"); + }}); + + assertEquals("Msg>&cError! The player Notch has not joined before!", output); + } + + @Test + @Order(16) + public void testTranslateNoColorNonExistentNode() { + // should return null and debug "node does not exist" + assertNull(localeProviderGroup1.translateNoColor("non-existent", new HashMap<>())); + } + + @Test + @Order(17) + public void testTranslateNoColorEmptyNode() { + // should return null and debug "invalid node name" + assertNull(localeProviderGroup1.translateNoColor("", new HashMap<>())); + } + + @Test + @Order(18) + public void testTranslateNoColorNullNode() { + // should return null and debug "invalid node name" + assertNull(localeProviderGroup1.translateNoColor(null, new HashMap<>())); + } + + @Test + @Order(19) + public void testGetEnum() { + // Sanity check - make sure translation works as expected + assertEquals("network-name", Values.NETWORK_NAME.name().toLowerCase().replace("_", "-")); + // Should translate to network-name and return the given value + assertEquals("&bDumb Dog Diner", localeProviderGroup1.get(Values.NETWORK_NAME)); + } + + @Test + @Order(20) + public void testGetWithNameAndNode() { + assertEquals("&bDumb Dog Diner", localeProviderGroup1.get("messages.en_us", "network-name")); + } + + @Test + @Order(21) + public void testGetWithNameAndNodeUnloadedLocale() { + assertThrows(IllegalArgumentException.class, () -> { + localeProviderGroup1.get("non-existent-locale", "network-name"); + }); + } + + @Test + @Order(22) + public void testGetDefault() { + assertEquals("&bDumb Dog Diner", localeProviderGroup1.getDefault("network-name", "&bExample Server")); + } + + @Test + @Order(23) + public void testGetDefaultNoNode() { + assertEquals("default value", localeProviderGroup1.getDefault("non-existent", "default value")); + } + + /* + Cannot be tested right now... + + public void testLoadLocaleInvalidFile() { + // Should return false and debug "encountered an error - skipping" + assertFalse(localeProviderGroup1.loadLocale("invalid.yml")); + }*/ + + @Test + public void testGetNoDefaultLocale() { + LocaleProvider localeProvider = new LocaleProvider(localeDirectoryGroup1); + assertNull(localeProvider.get("player-has-not-joined")); // Valid node + assertNull(localeProvider.get("")); // Invalid node + } + + @Test + public void testCreateLocaleProviderWithNonExistentFolder() { + // Make sure the file does not exist + assertFalse(nonExistentDirectory.exists()); + // Create a new instance of LocaleProvider (will create the directory) + new LocaleProvider(nonExistentDirectory); + // Make sure that it now exists and is a directory + assertTrue(nonExistentDirectory.exists()); + assertTrue(nonExistentDirectory.isDirectory()); + } + + @Test + public void testCreateLocaleProviderAndLoadAllLocales() { + LocaleProvider localeProvider = new LocaleProvider(localeDirectoryGroup1); + + // Load all locales, and assert that only one was loaded. + // There are 2 files in the given directory, one .yml file and one .txt + // This should return 1 and ignore the txt file + assertEquals(1, localeProvider.loadAllLocales()); + } + +} diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/IPUtilTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/IPUtilTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/IPUtilTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/IPUtilTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/LuhnTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/LuhnTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/LuhnTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/LuhnTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtilTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtilTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtilTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/MemoryUtilTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/NotificationTypeTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/NotificationTypeTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/NotificationTypeTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/NotificationTypeTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/NumberUtilTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/NumberUtilTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/NumberUtilTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/NumberUtilTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/StringUtilTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java similarity index 92% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java index 09bd8dce..397fe385 100644 --- a/src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/TextUtilTest.java @@ -4,7 +4,10 @@ */ package com.dumbdogdiner.stickyapi.common.util; -import com.google.common.io.CharStreams; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + import org.junit.jupiter.api.Test; import java.text.MessageFormat; @@ -12,9 +15,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - public class TextUtilTest { @Test public void testIsCharacterSupportedTrueBasicPlaneUtf16() { diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/TimeUtilTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/TimeUtilTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/TimeUtilTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/TimeUtilTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilInvokeProtectedMethodClassTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilInvokeProtectedMethodClassTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilInvokeProtectedMethodClassTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilInvokeProtectedMethodClassTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilNoSuchFieldTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilNoSuchFieldTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilNoSuchFieldTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilNoSuchFieldTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilTest.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/util/reflection/ReflectionUtilTest.java diff --git a/src/test/java/com/dumbdogdiner/stickyapi_tests_common/TestsCommon.java b/common/src/test/java/com/dumbdogdiner/stickyapi_tests_common/TestsCommon.java similarity index 100% rename from src/test/java/com/dumbdogdiner/stickyapi_tests_common/TestsCommon.java rename to common/src/test/java/com/dumbdogdiner/stickyapi_tests_common/TestsCommon.java diff --git a/common/src/test/resources/localeprovider/group1/ignored.txt b/common/src/test/resources/localeprovider/group1/ignored.txt new file mode 100644 index 00000000..f51d7add --- /dev/null +++ b/common/src/test/resources/localeprovider/group1/ignored.txt @@ -0,0 +1,6 @@ +==== + Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + Licensed under the MIT license, see LICENSE for more information... +==== + +(LocaleProvider should ignore this file) \ No newline at end of file diff --git a/common/src/test/resources/localeprovider/group1/messages.en_us.yml b/common/src/test/resources/localeprovider/group1/messages.en_us.yml new file mode 100644 index 00000000..9f62345e --- /dev/null +++ b/common/src/test/resources/localeprovider/group1/messages.en_us.yml @@ -0,0 +1,86 @@ +# SRC: https://github.com/DumbDogDiner/StickyCommands/blob/master/bukkit/src/main/resources/messages.en_us.yml +# StickyCommands Translation file +# ------------------------- + +# Messages.yml - All plugin text is in this file +# +# Anything between curley brackets is replaced with the values of the named variables. + +# Global variables, you can use these in any message in this file. +newline: "&8&l» " +prefix: "&b&lStickyCommands {newline}" +network-name: "&bDumb Dog Diner" +website: "dumbdogdiner.com" + +# Common error messages used throughout the plugin +invalid-syntax: "{prefix}&cInvalid Syntax! Please use &f{syntax}&c!" +server-error: "{prefix}&cThe server encountered an error, please try again later." +no-permission: "{prefix}&cError! Permission denied!" +player-does-not-exist: "{prefix}&cError! The player {target} does not exist!" +player-has-not-joined: "{prefix}&cError! The player {target} has not joined before!" +must-be-player: "{prefix}&cYou must be a player to execute this command!" +not-online-player: "{prefix}&c Error! {player} is not online!" +invalid-group: "{prefix}&cError! Group {GROUP} is invalid!" + +# The config supports new lines (\n), it can be used on any node +whois-message: "{prefix}&bWhois data for {target}\n{newline}&b{target_online|yesno:'&aOnline,&cOffline'} &bsince: &f{target_last_seen|expiry}\n{newline}&bIP: &f{target_ipaddress}\n{newline}&bFirst Login: &f{target_first_seen|expiry}\n{newline}&bLast Login: &f{target_last_seen|expiry}\n{newline}&bLast Server: &f{target_last_server}\n{newline}&bFly/Walk: &f{target_fly_speed}&b / &f{target_walk_speed}" +seen-message: "{prefix}&f{target} &bhas been {target_online|yesno:'&aOnline,&cOffline'}\n{newline} &bSince: &f{target_last_seen|expiry}\n{newline} &bOn Server: &f{target_last_server}" +top-message: "{prefix}&bWoosh! You're at the top!" +jump-message: "{prefix}&bWEEEEE!!!" +speed-message: "{prefix}&bYour {player_flying|yesno:'fly,walk'} speed has been set to &f{player_speed}&b!" +reload: + configs-success: "{prefix}&aReloaded configuration and messages successfully!" + database-success: "{prefix}&aReloaded configuration and messages successfully!" + error: "{prefix}&cThere was an error reloading StickyCommands, please see console for details!" + +back: + no-previous: "{prefix}&cNo previous location found!" + teleported: "{prefix}&bYou have been returned to your last location!" + teleported-other: "{prefix}&bReturned &f{target} &bto their last location!" + +sell: + cannot-sell: "{prefix}&cThis item cannot be sold!" + bad-worth: "{prefix}&f1 {item} &cis worth a negative amount &f(${single_worth}) &cand cannot be sold &4(Please ask a developer)" + worth-message: "{prefix}&f1 {item} &bis worth &f${single_worth} &7(Hand: ${hand_worth}, Inventory: ${inventory_worth})" + sell-message: "{prefix}&bYou sold &f{amount} {item} &bfor &f${worth}&b!" + must-confirm: "{prefix}&cPlease confirm your sale by typing /sell [inventory/hand] confirm!" + log: + log-message: "{prefix}&bRecent sale logs" + log: "{newline}&7({short_date}) &f{log_player} &bsold &f{amount} {item} &bfor &f${price}" + log-hover: "&bSale &f#{saleid}\n&8&l» &bItem Sold:&f {item_enum}\n&8&l» &bAmount Sold:&f {amount}\n&8&l» &bNew Balance:&f &2(+${price})\n&8&l» &bSold:&f {date_duration}\n&8&l» &bTransaction ID:&f {saleid}" + no-sales: "{prefix}&bThere have been no sales!" + paginator: "{prefix}&bpage &f{current}&b/&f{total}" + +afk: + not-afk: "&7&o* {player} is no longer AFK!" + afk: "&7&o* {player} is now AFK!" + afk-kick: "&cYou have been AFK for {time|duration} and have been kicked!" + +hat: + no-hat: "{prefix}&bYou do not have a hat!" + new-hat: "{prefix}&bEnjoy your new hat!" + remove-hat: "{prefix}&bYour hat has been removed!" +item-message: "{prefix}&bGave you &f{amount} {item}&b!" + +kill: + you-were-killed: "{prefix}&bThou hast been slain!" + you-killed: "{prefix}&bYou killed &f{target}" + suicide: "{prefix}&bYou magically died!" + +smite: + smite-other-player: "{prefix}&bYour fury reigns down on &f{target}&b!" + smite-block: "{prefix}&bYour fury reigns down on the block at &f{location_x}, {location_y}, {location_z} &bof world &f{world}" + smite-message: "{prefix}&bThou hast been smitten!" + smite-immune: "{prefix}&f{target}&c is immune to your wrath!" + yourself: "{prefix}&bYou have smitten yourself!" + +powertool: + cleared: "{prefix}&bCleared your powertool!" + assigned: "{prefix}&bPowertool created with command &f\"{command}\"" + cannot-bind-air: "{prefix}&cYou may not bind a command to your hand!" + toggled: "{prefix}&bYour powertool has been toggled {toggled|yesno:'&aOn,&cOff'}" + no-powertool: "{prefix}&cYou do not have a powertool to toggle!" + +player-time: + time-reset: "{prefix}&bYour time has been synced with the server &f({time} ticks)&b!" + time-set: "{prefix}&bYour time has been set to &f{time} ticks&b{relative|empty_if_false:\" relative to server time\"}!" \ No newline at end of file diff --git a/common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..ca6ee9ce --- /dev/null +++ b/common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file diff --git a/config/build.gradle b/config/build.gradle new file mode 100644 index 00000000..6c72dfd9 --- /dev/null +++ b/config/build.gradle @@ -0,0 +1,10 @@ +dependencies { + // Dependencies available in both bukkit and bungee + compileOnly "org.yaml:snakeyaml:1.27" + + // Only included in paper? - could remove dep + compileOnly "commons-lang:commons-lang:2.6" + + // YamlProviderTest + testImplementation "com.google.guava:guava:30.1.1-jre" +} diff --git a/config/lombok.config b/config/lombok.config new file mode 100644 index 00000000..189c0bef --- /dev/null +++ b/config/lombok.config @@ -0,0 +1,3 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true diff --git a/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/Configuration.java b/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/Configuration.java new file mode 100644 index 00000000..2665f057 --- /dev/null +++ b/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/Configuration.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.config; + +/** + * Base interface for a configuration. + */ +public interface Configuration { + /** + * Gets the given string from the path, returning the given default value if not found. + * @param path The path of the string to get + * @param def The default value if the path is not found or is not a string + * @return The requested string. + */ + public String getString(String path, String def); + + /** + * Gets the given string from the path. + * @param path The path of the string to get + * @return The requested string, or null. + */ + public String getString(String path); +} diff --git a/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/FileConfiguration.java b/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/FileConfiguration.java new file mode 100644 index 00000000..ee41f9ad --- /dev/null +++ b/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/FileConfiguration.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.config; + +import java.io.File; +import java.io.FileWriter; + +/** + * Interface for File-based Configurations. + */ +public interface FileConfiguration extends Configuration { + + /** + * Reload the current configuration, for example to load new data. + * This will reload the configuration file from the filesystem into memory, + * overwriting the currently loaded data. + */ + public void reload(); + + /** + * Save the configuration to the given string path. + * + * @param path {@link String} output filename path + * @return Returns a {@link Boolean} value depending on if the save was successful or not + */ + public boolean save(String path); + + /** + * + * @param output {@link File} to output to + * @return Returns a {@link Boolean} value depending on if the save was successful or not + */ + public boolean save(File output); + + /** + * Save the configuration to the given FileWriter. + * + * @param output {@link FileWriter} to output to + */ + public void save(FileWriter output); +} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/package-info.java b/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/package-info.java similarity index 80% rename from src/main/java/com/dumbdogdiner/stickyapi/common/configuration/package-info.java rename to config/src/main/java/com/dumbdogdiner/stickyapi/common/config/package-info.java index 8250a0d3..7bc672f8 100644 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/package-info.java +++ b/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/package-info.java @@ -5,4 +5,4 @@ /** * Classes dedicated to handling a plugin's runtime configuration. */ -package com.dumbdogdiner.stickyapi.common.configuration; +package com.dumbdogdiner.stickyapi.common.config; diff --git a/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/providers/YamlProvider.java b/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/providers/YamlProvider.java new file mode 100644 index 00000000..3ea6d5a6 --- /dev/null +++ b/config/src/main/java/com/dumbdogdiner/stickyapi/common/config/providers/YamlProvider.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.config.providers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.dumbdogdiner.stickyapi.common.config.FileConfiguration; + +import org.apache.commons.lang.Validate; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; + +public class YamlProvider implements FileConfiguration { + + private ConcurrentHashMap data; + + private InputStream inputStream; + + public YamlProvider(InputStream stream) { + Validate.notNull(stream, "InputStream cannot be null!"); + + this.inputStream = stream; + this.reload(); + } + + public YamlProvider(File file) throws FileNotFoundException { + this(new FileInputStream(file)); + } + + public void reload() { + // Attempt to (re)load the stream + + Yaml yaml = new Yaml(); + + // If we load to a ConcurrentHashMap directly, the map doesn't populate with our data + Map obj = yaml.load(this.inputStream); + + // Convert the loaded Map to a ConcurrentHashMap + this.data = new ConcurrentHashMap(obj); + } + + @Override + public String getString(String path, String def) { + Object value = this.data.get(path); + return (value != null) ? value.toString() : def; + } + + @Override + public String getString(String path) { + Object value = this.data.get(path); + return (value != null) ? value.toString() : null; + } + + @Override + public boolean save(String path) { + FileWriter fileWriter; + try { + // Attempt to create the FileWriter object (can throw IOException) + fileWriter = new FileWriter(path); + + // Save the config + this.save(fileWriter); + + // Saved successfully, return true + return true; + } catch (IOException e) { + // creating the FileWriter errored, so return false + return false; + } + + } + + public boolean save(File output) { + FileWriter fileWriter; + try { + // Attempt to create the FileWriter object (can throw IOException) + fileWriter = new FileWriter(output); + + // Save the config + this.save(fileWriter); + + // Saved successfully, return true + return true; + } catch (IOException e) { + // creating the FileWriter errored, so return false + return false; + } + } + + @Override + public void save(FileWriter output) { + // Generate dumper options + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setIndent(2); + options.setPrettyFlow(true); + + // Create a new yaml object with our options + Yaml yaml = new Yaml(options); + + // Write the data + yaml.dump(data, output); + + } +} diff --git a/config/src/test/java/com/dumbdogdiner/stickyapi/common/config/providers/YamlProviderTest.java b/config/src/test/java/com/dumbdogdiner/stickyapi/common/config/providers/YamlProviderTest.java new file mode 100644 index 00000000..f5ee03c2 --- /dev/null +++ b/config/src/test/java/com/dumbdogdiner/stickyapi/common/config/providers/YamlProviderTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.config.providers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; + +import com.dumbdogdiner.stickyapi.common.config.FileConfiguration; +import com.google.common.io.Files; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +@TestInstance(Lifecycle.PER_CLASS) +public class YamlProviderTest { + + private static final String exampleConfigPath = "src/test/resources/example.config.yml"; + + private FileConfiguration exampleFileConfig; + + @BeforeAll + public void prepareGetExampleFile() { + try { + exampleFileConfig = new YamlProvider(new FileInputStream(exampleConfigPath)); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testLoadFileAsFile() throws FileNotFoundException { + new YamlProvider(new File(exampleConfigPath)); + } + + @Test + public void testLoadFileAsInputStream() throws FileNotFoundException { + new YamlProvider(new FileInputStream(exampleConfigPath)); + } + + @Test + public void testGetValidString() { + assertEquals("Hello, World!", exampleFileConfig.getString("string")); + } + + @Test + public void testGetValidStringWithDefault() { + assertEquals("Hello, World!", exampleFileConfig.getString("string", "Goodbye, World!")); + } + + @Test + public void testGetNonExistentString() { + assertNull(exampleFileConfig.getString("non-existent")); + } + + @Test + public void testGetNonExistentStringWithDefault() { + assertEquals("Default Value", exampleFileConfig.getString("non-existent", "Default Value")); + } + + @Test + public void testSaveFileInputString() throws IOException { + String testOutput = "build/example.config.yml.string.test-save"; + // Write the file + assertTrue(exampleFileConfig.save(testOutput)); + // Assert that the original and saved files match (note that snakeyaml doesn't keep comments!) + // This *could* throw an IOException + Files.equal(new File(exampleConfigPath), new File(testOutput)); + } + + @Test + public void testSaveFileInputFile() throws IOException { + String testOutput = "build/example.config.yml.file.test-save"; + // Write the file + assertTrue(exampleFileConfig.save(new File(testOutput))); + // Assert that the original and saved files match (note that snakeyaml doesn't keep comments!) + // This *could* throw an IOException + Files.equal(new File(exampleConfigPath), new File(testOutput)); + } + + @Test + public void testSaveFileInputStringInvalid() { + assertFalse(exampleFileConfig.save("build")); + } + + @Test + public void testSaveFileInputFileInvalid() { + assertFalse(exampleFileConfig.save(new File("build"))); + } + + @Test + public void testAsynchronousRead() { + // create a new threadpool with n threads. + int threadCount = 3; + ExecutorService pool = Executors.newFixedThreadPool(threadCount); + AtomicBoolean didFail = new AtomicBoolean(); + // create n tasks and submit them to the pool. + for (int i = 0; i < threadCount; i++) { + pool.submit(() -> { + if (!exampleFileConfig.getString("string").equals("Hello, World!")) { + didFail.set(true); + } + }); + } + // wait for pool to finish execution. + pool.shutdown(); + assertFalse(didFail.get()); + } + + // This does not work yet - need to implement write. + // @Test + // public void testAsynchronousWrite() { } +} diff --git a/config/src/test/resources/example.config.yml b/config/src/test/resources/example.config.yml new file mode 100644 index 00000000..9dac156c --- /dev/null +++ b/config/src/test/resources/example.config.yml @@ -0,0 +1,4 @@ +string: "Hello, World!" +parent: + child: + child2: "value" diff --git a/settings.gradle b/settings.gradle index d43c4dab..d107c168 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,6 @@ -rootProject.name = 'stickyapi' \ No newline at end of file +rootProject.name = "stickyapi" +include ":common" +include ":common:serverversion" // subproject that's shaded into common +include ":config" // common subproject; not included in common jar +include ":bukkit" +include ":bungee" diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java deleted file mode 100644 index 048460d4..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import java.util.Map; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Represents a source of configurable options and settings - */ -public interface Configuration extends ConfigurationSection { - /** - * Sets the default value of the given path as provided. - *

- * If no source {@link Configuration} was provided as a default collection, then - * a new {@link MemoryConfiguration} will be created to hold the new default - * value. - *

- * If value is null, the value will be removed from the default Configuration - * source. - * - * @param path Path of the value to set. - * @param value Value to set the default to. - * @throws IllegalArgumentException Thrown if path is null. - */ - @Override - public void addDefault(@NotNull String path, @Nullable Object value); - - /** - * Sets the default values of the given paths as provided. - *

- * If no source {@link Configuration} was provided as a default collection, then - * a new {@link MemoryConfiguration} will be created to hold the new default - * values. - * - * @param defaults A map of Path{@literal ->}Values to add to defaults. - * @throws IllegalArgumentException Thrown if defaults is null. - */ - public void addDefaults(@NotNull Map defaults); - - /** - * Sets the default values of the given paths as provided. - *

- * If no source {@link Configuration} was provided as a default collection, then - * a new {@link MemoryConfiguration} will be created to hold the new default - * value. - *

- * This method will not hold a reference to the specified Configuration, nor - * will it automatically update if that Configuration ever changes. If you - * require this, you should set the default source with - * {@link #setDefaults(com.dumbdogdiner.stickyapi.common.configuration.Configuration)}. - * - * @param defaults A configuration holding a list of defaults to copy. - * @throws IllegalArgumentException Thrown if defaults is null or this. - */ - public void addDefaults(@NotNull Configuration defaults); - - /** - * Sets the source of all default values for this {@link Configuration}. - *

- * If a previous source was set, or previous default values were defined, then - * they will not be copied to the new source. - * - * @param defaults New source of default values for this configuration. - * @throws IllegalArgumentException Thrown if defaults is null or this. - */ - public void setDefaults(@NotNull Configuration defaults); - - /** - * Gets the source {@link Configuration} for this configuration. - *

- * If no configuration source was set, but default values were added, then a - * {@link MemoryConfiguration} will be returned. If no source was set and no - * defaults were set, then this method will return null. - * - * @return Configuration source for default values, or null if none exist. - */ - @Nullable - public Configuration getDefaults(); - - /** - * Gets the {@link ConfigurationOptions} for this {@link Configuration}. - *

- * All setters through this method are chainable. - * - * @return Options for this configuration - */ - @NotNull - public ConfigurationOptions options(); -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationOptions.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationOptions.java deleted file mode 100644 index f29e6471..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationOptions.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import org.jetbrains.annotations.NotNull; - -/** - * Various settings for controlling the input and output of a - * {@link Configuration} - */ -public class ConfigurationOptions { - private char pathSeparator = '.'; - private boolean copyDefaults = false; - private final Configuration configuration; - - protected ConfigurationOptions(@NotNull Configuration configuration) { - this.configuration = configuration; - } - - /** - * Returns the {@link Configuration} that this object is responsible for. - * - * @return Parent configuration - */ - @NotNull - public Configuration configuration() { - return configuration; - } - - /** - * Gets the char that will be used to separate {@link ConfigurationSection}s - *

- * This value does not affect how the {@link Configuration} is stored, only in - * how you access the data. The default value is '.'. - * - * @return Path separator - */ - public char pathSeparator() { - return pathSeparator; - } - - /** - * Sets the char that will be used to separate {@link ConfigurationSection}s - *

- * This value does not affect how the {@link Configuration} is stored, only in - * how you access the data. The default value is '.'. - * - * @param value Path separator - * @return This object, for chaining - */ - @NotNull - public ConfigurationOptions pathSeparator(char value) { - this.pathSeparator = value; - return this; - } - - /** - * Checks if the {@link Configuration} should copy values from its default - * {@link Configuration} directly. - *

- * If this is true, all values in the default Configuration will be directly - * copied, making it impossible to distinguish between values that were set and - * values that are provided by default. As a result, - * {@link ConfigurationSection#contains(java.lang.String)} will always return - * the same value as {@link ConfigurationSection#isSet(java.lang.String)}. The - * default value is false. - * - * @return Whether or not defaults are directly copied - */ - public boolean copyDefaults() { - return copyDefaults; - } - - /** - * Sets if the {@link Configuration} should copy values from its default - * {@link Configuration} directly. - *

- * If this is true, all values in the default Configuration will be directly - * copied, making it impossible to distinguish between values that were set and - * values that are provided by default. As a result, - * {@link ConfigurationSection#contains(java.lang.String)} will always return - * the same value as {@link ConfigurationSection#isSet(java.lang.String)}. The - * default value is false. - * - * @param value Whether or not defaults are directly copied - * @return This object, for chaining - */ - @NotNull - public ConfigurationOptions copyDefaults(boolean value) { - this.copyDefaults = value; - return this; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationSection.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationSection.java deleted file mode 100644 index bde145e0..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationSection.java +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.dumbdogdiner.stickyapi.common.configuration.serialization.ConfigurationSerializable; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Represents a section of a {@link Configuration} - */ -public interface ConfigurationSection { - /** - * Gets a set containing all keys in this section. - *

- * If deep is set to true, then this will contain all the keys within any child - * {@link ConfigurationSection}s (and their children, etc). These will be in a - * valid path notation for you to use. - *

- * If deep is set to false, then this will contain only the keys of any direct - * children, and not their own children. - * - * @param deep Whether or not to get a deep list, as opposed to a shallow list. - * @return Set of keys contained within this ConfigurationSection. - */ - @NotNull - public Set getKeys(boolean deep); - - /** - * Gets a Map containing all keys and their values for this section. - *

- * If deep is set to true, then this will contain all the keys and values within - * any child {@link ConfigurationSection}s (and their children, etc). These keys - * will be in a valid path notation for you to use. - *

- * If deep is set to false, then this will contain only the keys and values of - * any direct children, and not their own children. - * - * @param deep Whether or not to get a deep list, as opposed to a shallow list. - * @return Map of keys and values of this section. - */ - @NotNull - public Map getValues(boolean deep); - - /** - * Checks if this {@link ConfigurationSection} contains the given path. - *

- * If the value for the requested path does not exist but a default value has - * been specified, this will return true. - * - * @param path Path to check for existence. - * @return True if this section contains the requested path, either via default - * or being set. - * @throws IllegalArgumentException Thrown when path is null. - */ - public boolean contains(@NotNull String path); - - /** - * Checks if this {@link ConfigurationSection} contains the given path. - *

- * If the value for the requested path does not exist, the boolean parameter of - * true has been specified, a default value for the path exists, this will - * return true. - *

- * If a boolean parameter of false has been specified, true will only be - * returned if there is a set value for the specified path. - * - * @param path Path to check for existence. - * @param ignoreDefault Whether or not to ignore if a default value for the - * specified path exists. - * @return True if this section contains the requested path, or if a default - * value exist and the boolean parameter for this method is true. - * @throws IllegalArgumentException Thrown when path is null. - */ - public boolean contains(@NotNull String path, boolean ignoreDefault); - - /** - * Checks if this {@link ConfigurationSection} has a value set for the given - * path. - *

- * If the value for the requested path does not exist but a default value has - * been specified, this will still return false. - * - * @param path Path to check for existence. - * @return True if this section contains the requested path, regardless of - * having a default. - * @throws IllegalArgumentException Thrown when path is null. - */ - public boolean isSet(@NotNull String path); - - /** - * Gets the path of this {@link ConfigurationSection} from its root - * {@link Configuration} - *

- * For any {@link Configuration} themselves, this will return an empty string. - *

- * If the section is no longer contained within its root for any reason, such as - * being replaced with a different value, this may return null. - *

- * To retrieve the single name of this section, that is, the final part of the - * path returned by this method, you may use {@link #getName()}. - * - * @return Path of this section relative to its root - */ - @Nullable - public String getCurrentPath(); - - /** - * Gets the name of this individual {@link ConfigurationSection}, in the path. - *

- * This will always be the final part of {@link #getCurrentPath()}, unless the - * section is orphaned. - * - * @return Name of this section - */ - @NotNull - public String getName(); - - /** - * Gets the root {@link Configuration} that contains this - * {@link ConfigurationSection} - *

- * For any {@link Configuration} themselves, this will return its own object. - *

- * If the section is no longer contained within its root for any reason, such as - * being replaced with a different value, this may return null. - * - * @return Root configuration containing this section. - */ - @Nullable - public Configuration getRoot(); - - /** - * Gets the parent {@link ConfigurationSection} that directly contains this - * {@link ConfigurationSection}. - *

- * For any {@link Configuration} themselves, this will return null. - *

- * If the section is no longer contained within its parent for any reason, such - * as being replaced with a different value, this may return null. - * - * @return Parent section containing this section. - */ - @Nullable - public ConfigurationSection getParent(); - - /** - * Gets the requested Object by path. - *

- * If the Object does not exist but a default value has been specified, this - * will return the default value. If the Object does not exist and no default - * value was specified, this will return null. - * - * @param path Path of the Object to get. - * @return Requested Object. - */ - @Nullable - public Object get(@NotNull String path); - - /** - * Gets the requested Object by path, returning a default value if not found. - *

- * If the Object does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the Object to get. - * @param def The default value to return if the path is not found. - * @return Requested Object. - */ - @Nullable - public Object get(@NotNull String path, @Nullable Object def); - - /** - * Sets the specified path to the given value. - *

- * If value is null, the entry will be removed. Any existing entry will be - * replaced, regardless of what the new value is. - *

- * Some implementations may have limitations on what you may store. See their - * individual javadocs for details. No implementations should allow you to store - * {@link Configuration}s or {@link ConfigurationSection}s, please use - * {@link #createSection(java.lang.String)} for that. - * - * @param path Path of the object to set. - * @param value New value to set the path to. - */ - public void set(@NotNull String path, @Nullable Object value); - - /** - * Creates an empty {@link ConfigurationSection} at the specified path. - *

- * Any value that was previously set at this path will be overwritten. If the - * previous value was itself a {@link ConfigurationSection}, it will be - * orphaned. - * - * @param path Path to create the section at. - * @return Newly created section - */ - @NotNull - public ConfigurationSection createSection(@NotNull String path); - - /** - * Creates a {@link ConfigurationSection} at the specified path, with specified - * values. - *

- * Any value that was previously set at this path will be overwritten. If the - * previous value was itself a {@link ConfigurationSection}, it will be - * orphaned. - * - * @param path Path to create the section at. - * @param map The values to used. - * @return Newly created section - */ - @NotNull - public ConfigurationSection createSection(@NotNull String path, @NotNull Map map); - - // Primitives - /** - * Gets the requested String by path. - *

- * If the String does not exist but a default value has been specified, this - * will return the default value. If the String does not exist and no default - * value was specified, this will return null. - * - * @param path Path of the String to get. - * @return Requested String. - */ - @Nullable - public String getString(@NotNull String path); - - /** - * Gets the requested String by path, returning a default value if not found. - *

- * If the String does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the String to get. - * @param def The default value to return if the path is not found or is not a - * String. - * @return Requested String. - */ - @Nullable - public String getString(@NotNull String path, @Nullable String def); - - /** - * Checks if the specified path is a String. - *

- * If the path exists but is not a String, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * String and return appropriately. - * - * @param path Path of the String to check. - * @return Whether or not the specified path is a String. - */ - public boolean isString(@NotNull String path); - - /** - * Gets the requested int by path. - *

- * If the int does not exist but a default value has been specified, this will - * return the default value. If the int does not exist and no default value was - * specified, this will return 0. - * - * @param path Path of the int to get. - * @return Requested int. - */ - public int getInt(@NotNull String path); - - /** - * Gets the requested int by path, returning a default value if not found. - *

- * If the int does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the int to get. - * @param def The default value to return if the path is not found or is not an - * int. - * @return Requested int. - */ - public int getInt(@NotNull String path, int def); - - /** - * Checks if the specified path is an int. - *

- * If the path exists but is not a int, this will return false. If the path does - * not exist, this will return false. If the path does not exist but a default - * value has been specified, this will check if that default value is a int and - * return appropriately. - * - * @param path Path of the int to check. - * @return Whether or not the specified path is an int. - */ - public boolean isInt(@NotNull String path); - - /** - * Gets the requested boolean by path. - *

- * If the boolean does not exist but a default value has been specified, this - * will return the default value. If the boolean does not exist and no default - * value was specified, this will return false. - * - * @param path Path of the boolean to get. - * @return Requested boolean. - */ - public boolean getBoolean(@NotNull String path); - - /** - * Gets the requested boolean by path, returning a default value if not found. - *

- * If the boolean does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the boolean to get. - * @param def The default value to return if the path is not found or is not a - * boolean. - * @return Requested boolean. - */ - public boolean getBoolean(@NotNull String path, boolean def); - - /** - * Checks if the specified path is a boolean. - *

- * If the path exists but is not a boolean, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * boolean and return appropriately. - * - * @param path Path of the boolean to check. - * @return Whether or not the specified path is a boolean. - */ - public boolean isBoolean(@NotNull String path); - - /** - * Gets the requested double by path. - *

- * If the double does not exist but a default value has been specified, this - * will return the default value. If the double does not exist and no default - * value was specified, this will return 0. - * - * @param path Path of the double to get. - * @return Requested double. - */ - public double getDouble(@NotNull String path); - - /** - * Gets the requested double by path, returning a default value if not found. - *

- * If the double does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the double to get. - * @param def The default value to return if the path is not found or is not a - * double. - * @return Requested double. - */ - public double getDouble(@NotNull String path, double def); - - /** - * Checks if the specified path is a double. - *

- * If the path exists but is not a double, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * double and return appropriately. - * - * @param path Path of the double to check. - * @return Whether or not the specified path is a double. - */ - public boolean isDouble(@NotNull String path); - - /** - * Gets the requested long by path. - *

- * If the long does not exist but a default value has been specified, this will - * return the default value. If the long does not exist and no default value was - * specified, this will return 0. - * - * @param path Path of the long to get. - * @return Requested long. - */ - public long getLong(@NotNull String path); - - /** - * Gets the requested long by path, returning a default value if not found. - *

- * If the long does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the long to get. - * @param def The default value to return if the path is not found or is not a - * long. - * @return Requested long. - */ - public long getLong(@NotNull String path, long def); - - /** - * Checks if the specified path is a long. - *

- * If the path exists but is not a long, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * long and return appropriately. - * - * @param path Path of the long to check. - * @return Whether or not the specified path is a long. - */ - public boolean isLong(@NotNull String path); - - // Java - /** - * Gets the requested List by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return null. - * - * @param path Path of the List to get. - * @return Requested List. - */ - @Nullable - public List getList(@NotNull String path); - - /** - * Gets the requested List by path, returning a default value if not found. - *

- * If the List does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the List to get. - * @param def The default value to return if the path is not found or is not a - * List. - * @return Requested List. - */ - @Nullable - public List getList(@NotNull String path, @Nullable List def); - - /** - * Checks if the specified path is a List. - *

- * If the path exists but is not a List, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * List and return appropriately. - * - * @param path Path of the List to check. - * @return Whether or not the specified path is a List. - */ - public boolean isList(@NotNull String path); - - /** - * Gets the requested List of String by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a String if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of String. - */ - @NotNull - public List getStringList(@NotNull String path); - - /** - * Gets the requested List of Integer by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Integer if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Integer. - */ - @NotNull - public List getIntegerList(@NotNull String path); - - /** - * Gets the requested List of Boolean by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Boolean if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Boolean. - */ - @NotNull - public List getBooleanList(@NotNull String path); - - /** - * Gets the requested List of Double by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Double if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Double. - */ - @NotNull - public List getDoubleList(@NotNull String path); - - /** - * Gets the requested List of Float by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Float if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Float. - */ - @NotNull - public List getFloatList(@NotNull String path); - - /** - * Gets the requested List of Long by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Long if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Long. - */ - @NotNull - public List getLongList(@NotNull String path); - - /** - * Gets the requested List of Byte by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Byte if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Byte. - */ - @NotNull - public List getByteList(@NotNull String path); - - /** - * Gets the requested List of Character by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Character if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Character. - */ - @NotNull - public List getCharacterList(@NotNull String path); - - /** - * Gets the requested List of Short by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Short if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Short. - */ - @NotNull - public List getShortList(@NotNull String path); - - /** - * Gets the requested List of Maps by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Map if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Maps. - */ - @NotNull - public List> getMapList(@NotNull String path); - - // Bukkit - /** - * Gets the requested object at the given path. - * - * If the Object does not exist but a default value has been specified, this - * will return the default value. If the Object does not exist and no default - * value was specified, this will return null. - * - * Note: For example #getObject(path, String.class) is not - * equivalent to {@link #getString(String) #getString(path)} because - * {@link #getString(String) #getString(path)} converts internally all Objects - * to Strings. However, #getObject(path, Boolean.class) is equivalent to - * {@link #getBoolean(String) #getBoolean(path)} for example. - * - * @param the type of the requested object - * @param path the path to the object. - * @param clazz the type of the requested object - * @return Requested object - */ - @Nullable - public T getObject(@NotNull String path, @NotNull Class clazz); - - /** - * Gets the requested object at the given path, returning a default value if not - * found - * - * If the Object does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * Note: For example #getObject(path, String.class, def) is not - * equivalent to {@link #getString(String, String) #getString(path, def)} - * because {@link #getString(String, String) #getString(path, def)} converts - * internally all Objects to Strings. However, #getObject(path, Boolean.class, - * def) is equivalent to {@link #getBoolean(String, boolean) #getBoolean(path, - * def)} for example. - * - * @param the type of the requested object - * @param path the path to the object. - * @param clazz the type of the requested object - * @param def the default object to return if the object is not present at the - * path - * @return Requested object - */ - @Nullable - public T getObject(@NotNull String path, @NotNull Class clazz, @Nullable T def); - - /** - * Gets the requested {@link ConfigurationSerializable} object at the given - * path. - * - * If the Object does not exist but a default value has been specified, this - * will return the default value. If the Object does not exist and no default - * value was specified, this will return null. - * - * @param the type of {@link ConfigurationSerializable} - * @param path the path to the object. - * @param clazz the type of {@link ConfigurationSerializable} - * @return Requested {@link ConfigurationSerializable} object - */ - @Nullable - public T getSerializable(@NotNull String path, @NotNull Class clazz); - - /** - * Gets the requested {@link ConfigurationSerializable} object at the given - * path, returning a default value if not found - * - * If the Object does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param the type of {@link ConfigurationSerializable} - * @param path the path to the object. - * @param clazz the type of {@link ConfigurationSerializable} - * @param def the default object to return if the object is not present at the - * path - * @return Requested {@link ConfigurationSerializable} object - */ - @Nullable - public T getSerializable(@NotNull String path, @NotNull Class clazz, - @Nullable T def); - - /** - * Gets the requested ConfigurationSection by path. - *

- * If the ConfigurationSection does not exist but a default value has been - * specified, this will return the default value. If the ConfigurationSection - * does not exist and no default value was specified, this will return null. - * - * @param path Path of the ConfigurationSection to get. - * @return Requested ConfigurationSection. - */ - @Nullable - public ConfigurationSection getConfigurationSection(@NotNull String path); - - /** - * Checks if the specified path is a ConfigurationSection. - *

- * If the path exists but is not a ConfigurationSection, this will return false. - * If the path does not exist, this will return false. If the path does not - * exist but a default value has been specified, this will check if that default - * value is a ConfigurationSection and return appropriately. - * - * @param path Path of the ConfigurationSection to check. - * @return Whether or not the specified path is a ConfigurationSection. - */ - public boolean isConfigurationSection(@NotNull String path); - - /** - * Gets the equivalent {@link ConfigurationSection} from the default - * {@link Configuration} defined in {@link #getRoot()}. - *

- * If the root contains no defaults, or the defaults doesn't contain a value for - * this path, or the value at this path is not a {@link ConfigurationSection} - * then this will return null. - * - * @return Equivalent section in root configuration - */ - @Nullable - public ConfigurationSection getDefaultSection(); - - /** - * Sets the default value in the root at the given path as provided. - *

- * If no source {@link Configuration} was provided as a default collection, then - * a new {@link MemoryConfiguration} will be created to hold the new default - * value. - *

- * If value is null, the value will be removed from the default Configuration - * source. - *

- * If the value as returned by {@link #getDefaultSection()} is null, then this - * will create a new section at the path, replacing anything that may have - * existed there previously. - * - * @param path Path of the value to set. - * @param value Value to set the default to. - * @throws IllegalArgumentException Thrown if path is null. - */ - public void addDefault(@NotNull String path, @Nullable Object value); -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/InvalidConfigurationException.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/InvalidConfigurationException.java deleted file mode 100644 index 2d755098..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/InvalidConfigurationException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -/** - * Exception thrown when attempting to load an invalid {@link Configuration} - */ -@SuppressWarnings("serial") -public class InvalidConfigurationException extends Exception { - - /** - * Creates a new instance of InvalidConfigurationException without a message or - * cause. - */ - public InvalidConfigurationException() { - } - - /** - * Constructs an instance of InvalidConfigurationException with the specified - * message. - * - * @param msg The details of the exception. - */ - public InvalidConfigurationException(String msg) { - super(msg); - } - - /** - * Constructs an instance of InvalidConfigurationException with the specified - * cause. - * - * @param cause The cause of the exception. - */ - public InvalidConfigurationException(Throwable cause) { - super(cause); - } - - /** - * Constructs an instance of InvalidConfigurationException with the specified - * message and cause. - * - * @param cause The cause of the exception. - * @param msg The details of the exception. - */ - public InvalidConfigurationException(String msg, Throwable cause) { - super(msg, cause); - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfiguration.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfiguration.java deleted file mode 100644 index 88dff822..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfiguration.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import java.util.Map; -import org.apache.commons.lang.Validate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * This is a {@link Configuration} implementation that does not save or load - * from any source, and stores all values in memory only. This is useful for - * temporary Configurations for providing defaults. - */ -public class MemoryConfiguration extends MemorySection implements Configuration { - protected Configuration defaults; - protected MemoryConfigurationOptions options; - - /** - * Creates an empty {@link MemoryConfiguration} with no default values. - */ - public MemoryConfiguration() { - } - - /** - * Creates an empty {@link MemoryConfiguration} using the specified - * {@link Configuration} as a source for all default values. - * - * @param defaults Default value provider - * @throws IllegalArgumentException Thrown if defaults is null - */ - public MemoryConfiguration(@Nullable Configuration defaults) { - this.defaults = defaults; - } - - @Override - public void addDefault(@NotNull String path, @Nullable Object value) { - Validate.notNull(path, "Path may not be null"); - - if (defaults == null) { - defaults = new MemoryConfiguration(); - } - - defaults.set(path, value); - } - - @Override - public void addDefaults(@NotNull Map defaults) { - Validate.notNull(defaults, "Defaults may not be null"); - - for (Map.Entry entry : defaults.entrySet()) { - addDefault(entry.getKey(), entry.getValue()); - } - } - - @Override - public void addDefaults(@NotNull Configuration defaults) { - Validate.notNull(defaults, "Defaults may not be null"); - - addDefaults(defaults.getValues(true)); - } - - @Override - public void setDefaults(@NotNull Configuration defaults) { - Validate.notNull(defaults, "Defaults may not be null"); - - this.defaults = defaults; - } - - @Override - @Nullable - public Configuration getDefaults() { - return defaults; - } - - @Nullable - @Override - public ConfigurationSection getParent() { - return null; - } - - @Override - @NotNull - public MemoryConfigurationOptions options() { - if (options == null) { - options = new MemoryConfigurationOptions(this); - } - - return options; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfigurationOptions.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfigurationOptions.java deleted file mode 100644 index 61402e53..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfigurationOptions.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import org.jetbrains.annotations.NotNull; - -/** - * Various settings for controlling the input and output of a - * {@link MemoryConfiguration} - */ -public class MemoryConfigurationOptions extends ConfigurationOptions { - protected MemoryConfigurationOptions(@NotNull MemoryConfiguration configuration) { - super(configuration); - } - - @NotNull - @Override - public MemoryConfiguration configuration() { - return (MemoryConfiguration) super.configuration(); - } - - @NotNull - @Override - public MemoryConfigurationOptions copyDefaults(boolean value) { - super.copyDefaults(value); - return this; - } - - @NotNull - @Override - public MemoryConfigurationOptions pathSeparator(char value) { - super.pathSeparator(value); - return this; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemorySection.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemorySection.java deleted file mode 100644 index 523d1911..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemorySection.java +++ /dev/null @@ -1,882 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import static org.bukkit.util.NumberConversions.toDouble; -import static org.bukkit.util.NumberConversions.toInt; -import static org.bukkit.util.NumberConversions.toLong; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.dumbdogdiner.stickyapi.common.configuration.serialization.ConfigurationSerializable; - -import org.apache.commons.lang.Validate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * A type of {@link ConfigurationSection} that is stored in memory. - */ -public class MemorySection implements ConfigurationSection { - protected final Map map = new LinkedHashMap(); - private final Configuration root; - private final ConfigurationSection parent; - private final String path; - private final String fullPath; - - /** - * Creates an empty MemorySection for use as a root {@link Configuration} - * section. - *

- * Note that calling this without being yourself a {@link Configuration} will - * throw an exception! - * - * @throws IllegalStateException Thrown if this is not a {@link Configuration} - * root. - */ - protected MemorySection() { - if (!(this instanceof Configuration)) { - throw new IllegalStateException("Cannot construct a root MemorySection when not a Configuration"); - } - - this.path = ""; - this.fullPath = ""; - this.parent = null; - this.root = (Configuration) this; - } - - /** - * Creates an empty MemorySection with the specified parent and path. - * - * @param parent Parent section that contains this own section. - * @param path Path that you may access this section from via the root - * {@link Configuration}. - * @throws IllegalArgumentException Thrown is parent or path is null, or if - * parent contains no root Configuration. - */ - protected MemorySection(@NotNull ConfigurationSection parent, @NotNull String path) { - Validate.notNull(parent, "Parent cannot be null"); - Validate.notNull(path, "Path cannot be null"); - - this.path = path; - this.parent = parent; - this.root = parent.getRoot(); - - Validate.notNull(root, "Path cannot be orphaned"); - - this.fullPath = createPath(parent, path); - } - - @Override - @NotNull - public Set getKeys(boolean deep) { - Set result = new LinkedHashSet(); - - Configuration root = getRoot(); - if (root != null && root.options().copyDefaults()) { - ConfigurationSection defaults = getDefaultSection(); - - if (defaults != null) { - result.addAll(defaults.getKeys(deep)); - } - } - - mapChildrenKeys(result, this, deep); - - return result; - } - - @Override - @NotNull - public Map getValues(boolean deep) { - Map result = new LinkedHashMap(); - - Configuration root = getRoot(); - if (root != null && root.options().copyDefaults()) { - ConfigurationSection defaults = getDefaultSection(); - - if (defaults != null) { - result.putAll(defaults.getValues(deep)); - } - } - - mapChildrenValues(result, this, deep); - - return result; - } - - @Override - public boolean contains(@NotNull String path) { - return contains(path, false); - } - - @Override - public boolean contains(@NotNull String path, boolean ignoreDefault) { - return ((ignoreDefault) ? get(path, null) : get(path)) != null; - } - - @Override - public boolean isSet(@NotNull String path) { - Configuration root = getRoot(); - if (root == null) { - return false; - } - if (root.options().copyDefaults()) { - return contains(path); - } - return get(path, null) != null; - } - - @Override - @NotNull - public String getCurrentPath() { - return fullPath; - } - - @Override - @NotNull - public String getName() { - return path; - } - - @Override - @Nullable - public Configuration getRoot() { - return root; - } - - @Override - @Nullable - public ConfigurationSection getParent() { - return parent; - } - - @Override - public void addDefault(@NotNull String path, @Nullable Object value) { - Validate.notNull(path, "Path cannot be null"); - - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot add default without root"); - } - if (root == this) { - throw new UnsupportedOperationException("Unsupported addDefault(String, Object) implementation"); - } - root.addDefault(createPath(this, path), value); - } - - @Override - @Nullable - public ConfigurationSection getDefaultSection() { - Configuration root = getRoot(); - Configuration defaults = root == null ? null : root.getDefaults(); - - if (defaults != null) { - if (defaults.isConfigurationSection(getCurrentPath())) { - return defaults.getConfigurationSection(getCurrentPath()); - } - } - - return null; - } - - @Override - public void set(@NotNull String path, @Nullable Object value) { - Validate.notEmpty(path, "Cannot set to an empty path"); - - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot use section without a root"); - } - - final char separator = root.options().pathSeparator(); - // i1 is the leading (higher) index - // i2 is the trailing (lower) index - int i1 = -1, i2; - ConfigurationSection section = this; - while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { - String node = path.substring(i2, i1); - ConfigurationSection subSection = section.getConfigurationSection(node); - if (subSection == null) { - if (value == null) { - // no need to create missing sub-sections if we want to remove the value: - return; - } - section = section.createSection(node); - } else { - section = subSection; - } - } - - String key = path.substring(i2); - if (section == this) { - if (value == null) { - map.remove(key); - } else { - map.put(key, value); - } - } else { - section.set(key, value); - } - } - - @Override - @Nullable - public Object get(@NotNull String path) { - return get(path, getDefault(path)); - } - - @Override - @Nullable - public Object get(@NotNull String path, @Nullable Object def) { - Validate.notNull(path, "Path cannot be null"); - - if (path.length() == 0) { - return this; - } - - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot access section without a root"); - } - - final char separator = root.options().pathSeparator(); - // i1 is the leading (higher) index - // i2 is the trailing (lower) index - int i1 = -1, i2; - ConfigurationSection section = this; - while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { - section = section.getConfigurationSection(path.substring(i2, i1)); - if (section == null) { - return def; - } - } - - String key = path.substring(i2); - if (section == this) { - Object result = map.get(key); - return (result == null) ? def : result; - } - return section.get(key, def); - } - - @Override - @NotNull - public ConfigurationSection createSection(@NotNull String path) { - Validate.notEmpty(path, "Cannot create section at empty path"); - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot create section without a root"); - } - - final char separator = root.options().pathSeparator(); - // i1 is the leading (higher) index - // i2 is the trailing (lower) index - int i1 = -1, i2; - ConfigurationSection section = this; - while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { - String node = path.substring(i2, i1); - ConfigurationSection subSection = section.getConfigurationSection(node); - if (subSection == null) { - section = section.createSection(node); - } else { - section = subSection; - } - } - - String key = path.substring(i2); - if (section == this) { - ConfigurationSection result = new MemorySection(this, key); - map.put(key, result); - return result; - } - return section.createSection(key); - } - - @Override - @NotNull - public ConfigurationSection createSection(@NotNull String path, @NotNull Map map) { - ConfigurationSection section = createSection(path); - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() instanceof Map) { - section.createSection(entry.getKey().toString(), (Map) entry.getValue()); - } else { - section.set(entry.getKey().toString(), entry.getValue()); - } - } - - return section; - } - - // Primitives - @Override - @Nullable - public String getString(@NotNull String path) { - Object def = getDefault(path); - return getString(path, def != null ? def.toString() : null); - } - - @Override - @Nullable - public String getString(@NotNull String path, @Nullable String def) { - Object val = get(path, def); - return (val != null) ? val.toString() : def; - } - - @Override - public boolean isString(@NotNull String path) { - Object val = get(path); - return val instanceof String; - } - - @Override - public int getInt(@NotNull String path) { - Object def = getDefault(path); - return getInt(path, (def instanceof Number) ? toInt(def) : 0); - } - - @Override - public int getInt(@NotNull String path, int def) { - Object val = get(path, def); - return (val instanceof Number) ? toInt(val) : def; - } - - @Override - public boolean isInt(@NotNull String path) { - Object val = get(path); - return val instanceof Integer; - } - - @Override - public boolean getBoolean(@NotNull String path) { - Object def = getDefault(path); - return getBoolean(path, (def instanceof Boolean) ? (Boolean) def : false); - } - - @Override - public boolean getBoolean(@NotNull String path, boolean def) { - Object val = get(path, def); - return (val instanceof Boolean) ? (Boolean) val : def; - } - - @Override - public boolean isBoolean(@NotNull String path) { - Object val = get(path); - return val instanceof Boolean; - } - - @Override - public double getDouble(@NotNull String path) { - Object def = getDefault(path); - return getDouble(path, (def instanceof Number) ? toDouble(def) : 0); - } - - @Override - public double getDouble(@NotNull String path, double def) { - Object val = get(path, def); - return (val instanceof Number) ? toDouble(val) : def; - } - - @Override - public boolean isDouble(@NotNull String path) { - Object val = get(path); - return val instanceof Double; - } - - @Override - public long getLong(@NotNull String path) { - Object def = getDefault(path); - return getLong(path, (def instanceof Number) ? toLong(def) : 0); - } - - @Override - public long getLong(@NotNull String path, long def) { - Object val = get(path, def); - return (val instanceof Number) ? toLong(val) : def; - } - - @Override - public boolean isLong(@NotNull String path) { - Object val = get(path); - return val instanceof Long; - } - - // Java - @Override - @Nullable - public List getList(@NotNull String path) { - Object def = getDefault(path); - return getList(path, (def instanceof List) ? (List) def : null); - } - - @Override - @Nullable - public List getList(@NotNull String path, @Nullable List def) { - Object val = get(path, def); - return (List) ((val instanceof List) ? val : def); - } - - @Override - public boolean isList(@NotNull String path) { - Object val = get(path); - return val instanceof List; - } - - @Override - @NotNull - public List getStringList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if ((object instanceof String) || (isPrimitiveWrapper(object))) { - result.add(String.valueOf(object)); - } - } - - return result; - } - - @Override - @NotNull - public List getIntegerList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Integer) { - result.add((Integer) object); - } else if (object instanceof String) { - try { - result.add(Integer.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((int) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).intValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getBooleanList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Boolean) { - result.add((Boolean) object); - } else if (object instanceof String) { - if (Boolean.TRUE.toString().equals(object)) { - result.add(true); - } else if (Boolean.FALSE.toString().equals(object)) { - result.add(false); - } - } - } - - return result; - } - - @Override - @NotNull - public List getDoubleList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Double) { - result.add((Double) object); - } else if (object instanceof String) { - try { - result.add(Double.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((double) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).doubleValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getFloatList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Float) { - result.add((Float) object); - } else if (object instanceof String) { - try { - result.add(Float.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((float) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).floatValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getLongList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Long) { - result.add((Long) object); - } else if (object instanceof String) { - try { - result.add(Long.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((long) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).longValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getByteList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Byte) { - result.add((Byte) object); - } else if (object instanceof String) { - try { - result.add(Byte.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((byte) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).byteValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getCharacterList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Character) { - result.add((Character) object); - } else if (object instanceof String) { - String str = (String) object; - - if (str.length() == 1) { - result.add(str.charAt(0)); - } - } else if (object instanceof Number) { - result.add((char) ((Number) object).intValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getShortList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Short) { - result.add((Short) object); - } else if (object instanceof String) { - try { - result.add(Short.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((short) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).shortValue()); - } - } - - return result; - } - - @Override - @NotNull - public List> getMapList(@NotNull String path) { - List list = getList(path); - List> result = new ArrayList>(); - - if (list == null) { - return result; - } - - for (Object object : list) { - if (object instanceof Map) { - result.add((Map) object); - } - } - - return result; - } - - // Bukkit - @Nullable - @Override - public T getObject(@NotNull String path, @NotNull Class clazz) { - Validate.notNull(clazz, "Class cannot be null"); - Object def = getDefault(path); - return getObject(path, clazz, (def != null && clazz.isInstance(def)) ? clazz.cast(def) : null); - } - - @Nullable - @Override - public T getObject(@NotNull String path, @NotNull Class clazz, @Nullable T def) { - Validate.notNull(clazz, "Class cannot be null"); - Object val = get(path, def); - return (val != null && clazz.isInstance(val)) ? clazz.cast(val) : def; - } - - @Nullable - @Override - public T getSerializable(@NotNull String path, @NotNull Class clazz) { - return getObject(path, clazz); - } - - @Nullable - @Override - public T getSerializable(@NotNull String path, @NotNull Class clazz, - @Nullable T def) { - return getObject(path, clazz, def); - } - - @Override - @Nullable - public ConfigurationSection getConfigurationSection(@NotNull String path) { - Object val = get(path, null); - if (val != null) { - return (val instanceof ConfigurationSection) ? (ConfigurationSection) val : null; - } - - val = get(path, getDefault(path)); - return (val instanceof ConfigurationSection) ? createSection(path) : null; - } - - @Override - public boolean isConfigurationSection(@NotNull String path) { - Object val = get(path); - return val instanceof ConfigurationSection; - } - - protected boolean isPrimitiveWrapper(@Nullable Object input) { - return input instanceof Integer || input instanceof Boolean || input instanceof Character - || input instanceof Byte || input instanceof Short || input instanceof Double || input instanceof Long - || input instanceof Float; - } - - @Nullable - protected Object getDefault(@NotNull String path) { - Validate.notNull(path, "Path cannot be null"); - - Configuration root = getRoot(); - Configuration defaults = root == null ? null : root.getDefaults(); - return (defaults == null) ? null : defaults.get(createPath(this, path)); - } - - protected void mapChildrenKeys(@NotNull Set output, @NotNull ConfigurationSection section, boolean deep) { - if (section instanceof MemorySection) { - MemorySection sec = (MemorySection) section; - - for (Map.Entry entry : sec.map.entrySet()) { - output.add(createPath(section, entry.getKey(), this)); - - if ((deep) && (entry.getValue() instanceof ConfigurationSection)) { - ConfigurationSection subsection = (ConfigurationSection) entry.getValue(); - mapChildrenKeys(output, subsection, deep); - } - } - } else { - Set keys = section.getKeys(deep); - - for (String key : keys) { - output.add(createPath(section, key, this)); - } - } - } - - protected void mapChildrenValues(@NotNull Map output, @NotNull ConfigurationSection section, - boolean deep) { - if (section instanceof MemorySection) { - MemorySection sec = (MemorySection) section; - - for (Map.Entry entry : sec.map.entrySet()) { - // Because of the copyDefaults call potentially copying out of order, we must - // remove and then add in our saved order - // This means that default values we haven't set end up getting placed first - // See SPIGOT-4558 for an example using spigot.yml - watch subsections move - // around to default order - String childPath = createPath(section, entry.getKey(), this); - output.remove(childPath); - output.put(childPath, entry.getValue()); - - if (entry.getValue() instanceof ConfigurationSection) { - if (deep) { - mapChildrenValues(output, (ConfigurationSection) entry.getValue(), deep); - } - } - } - } else { - Map values = section.getValues(deep); - - for (Map.Entry entry : values.entrySet()) { - output.put(createPath(section, entry.getKey(), this), entry.getValue()); - } - } - } - - /** - * Creates a full path to the given {@link ConfigurationSection} from its root - * {@link Configuration}. - *

- * You may use this method for any given {@link ConfigurationSection}, not only - * {@link MemorySection}. - * - * @param section Section to create a path for. - * @param key Name of the specified section. - * @return Full path of the section from its root. - */ - @NotNull - public static String createPath(@NotNull ConfigurationSection section, @Nullable String key) { - return createPath(section, key, (section == null) ? null : section.getRoot()); - } - - /** - * Creates a relative path to the given {@link ConfigurationSection} from the - * given relative section. - *

- * You may use this method for any given {@link ConfigurationSection}, not only - * {@link MemorySection}. - * - * @param section Section to create a path for. - * @param key Name of the specified section. - * @param relativeTo Section to create the path relative to. - * @return Full path of the section from its root. - */ - @NotNull - public static String createPath(@NotNull ConfigurationSection section, @Nullable String key, - @Nullable ConfigurationSection relativeTo) { - Validate.notNull(section, "Cannot create path without a section"); - Configuration root = section.getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot create path without a root"); - } - char separator = root.options().pathSeparator(); - - StringBuilder builder = new StringBuilder(); - if (section != null) { - for (ConfigurationSection parent = section; (parent != null) - && (parent != relativeTo); parent = parent.getParent()) { - if (builder.length() > 0) { - builder.insert(0, separator); - } - - builder.insert(0, parent.getName()); - } - } - - if ((key != null) && (key.length() > 0)) { - if (builder.length() > 0) { - builder.append(separator); - } - - builder.append(key); - } - - return builder.toString(); - } - - @Override - public String toString() { - Configuration root = getRoot(); - return new StringBuilder().append(getClass().getSimpleName()).append("[path='").append(getCurrentPath()) - .append("', root='").append(root == null ? null : root.getClass().getSimpleName()).append("']") - .toString(); - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfiguration.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfiguration.java deleted file mode 100644 index 07cf5928..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfiguration.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import com.google.common.base.Charsets; -import com.google.common.io.Files; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; -import org.apache.commons.lang.Validate; -import com.dumbdogdiner.stickyapi.common.configuration.Configuration; -import com.dumbdogdiner.stickyapi.common.configuration.InvalidConfigurationException; -import com.dumbdogdiner.stickyapi.common.configuration.MemoryConfiguration; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * This is a base class for all File based implementations of - * {@link Configuration} - */ -public abstract class FileConfiguration extends MemoryConfiguration { - - /** - * Creates an empty {@link FileConfiguration} with no default values. - */ - public FileConfiguration() { - super(); - } - - /** - * Creates an empty {@link FileConfiguration} using the specified - * {@link Configuration} as a source for all default values. - * - * @param defaults Default value provider - */ - public FileConfiguration(@Nullable Configuration defaults) { - super(defaults); - } - - /** - * Saves this {@link FileConfiguration} to the specified location. - *

- * If the file does not exist, it will be created. If already exists, it will be - * overwritten. If it cannot be overwritten or created, an exception will be - * thrown. - *

- * This method will save using the system default encoding, or possibly using - * UTF8. - * - * @param file File to save to. - * @throws IOException Thrown when the given file cannot be written - * to for any reason. - * @throws IllegalArgumentException Thrown when file is null. - */ - public void save(@NotNull File file) throws IOException { - Validate.notNull(file, "File cannot be null"); - - Files.createParentDirs(file); - - String data = saveToString(); - - Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8); - - try { - writer.write(data); - } finally { - writer.close(); - } - } - - /** - * Saves this {@link FileConfiguration} to the specified location. - *

- * If the file does not exist, it will be created. If already exists, it will be - * overwritten. If it cannot be overwritten or created, an exception will be - * thrown. - *

- * This method will save using the system default encoding, or possibly using - * UTF8. - * - * @param file File to save to. - * @throws IOException Thrown when the given file cannot be written - * to for any reason. - * @throws IllegalArgumentException Thrown when file is null. - */ - public void save(@NotNull String file) throws IOException { - Validate.notNull(file, "File cannot be null"); - - save(new File(file)); - } - - /** - * Saves this {@link FileConfiguration} to a string, and returns it. - * - * @return String containing this configuration. - */ - @NotNull - public abstract String saveToString(); - - /** - * Loads this {@link FileConfiguration} from the specified location. - *

- * All the values contained within this configuration will be removed, leaving - * only settings and defaults, and the new values will be loaded from the given - * file. - *

- * If the file cannot be loaded for any reason, an exception will be thrown. - * - * @param file File to load from. - * @throws FileNotFoundException Thrown when the given file cannot be - * opened. - * @throws IOException Thrown when the given file cannot be - * read. - * @throws InvalidConfigurationException Thrown when the given file is not a - * valid Configuration. - * @throws IllegalArgumentException Thrown when file is null. - */ - public void load(@NotNull File file) throws FileNotFoundException, IOException, InvalidConfigurationException { - Validate.notNull(file, "File cannot be null"); - - final FileInputStream stream = new FileInputStream(file); - - load(new InputStreamReader(stream, Charsets.UTF_8)); - } - - /** - * Loads this {@link FileConfiguration} from the specified reader. - *

- * All the values contained within this configuration will be removed, leaving - * only settings and defaults, and the new values will be loaded from the given - * stream. - * - * @param reader the reader to load from - * @throws IOException thrown when underlying reader throws an - * IOException - * @throws InvalidConfigurationException thrown when the reader does not - * represent a valid Configuration - * @throws IllegalArgumentException thrown when reader is null - */ - public void load(@NotNull Reader reader) throws IOException, InvalidConfigurationException { - BufferedReader input = reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader); - - StringBuilder builder = new StringBuilder(); - - try { - String line; - - while ((line = input.readLine()) != null) { - builder.append(line); - builder.append('\n'); - } - } finally { - input.close(); - } - - loadFromString(builder.toString()); - } - - /** - * Loads this {@link FileConfiguration} from the specified location. - *

- * All the values contained within this configuration will be removed, leaving - * only settings and defaults, and the new values will be loaded from the given - * file. - *

- * If the file cannot be loaded for any reason, an exception will be thrown. - * - * @param file File to load from. - * @throws FileNotFoundException Thrown when the given file cannot be - * opened. - * @throws IOException Thrown when the given file cannot be - * read. - * @throws InvalidConfigurationException Thrown when the given file is not a - * valid Configuration. - * @throws IllegalArgumentException Thrown when file is null. - */ - public void load(@NotNull String file) throws FileNotFoundException, IOException, InvalidConfigurationException { - Validate.notNull(file, "File cannot be null"); - - load(new File(file)); - } - - /** - * Loads this {@link FileConfiguration} from the specified string, as opposed to - * from file. - *

- * All the values contained within this configuration will be removed, leaving - * only settings and defaults, and the new values will be loaded from the given - * string. - *

- * If the string is invalid in any way, an exception will be thrown. - * - * @param contents Contents of a Configuration to load. - * @throws InvalidConfigurationException Thrown if the specified string is - * invalid. - * @throws IllegalArgumentException Thrown if contents is null. - */ - public abstract void loadFromString(@NotNull String contents) throws InvalidConfigurationException; - - /** - * Compiles the header for this {@link FileConfiguration} and returns the - * result. - *

- * This will use the header from {@link #options()} -> - * {@link FileConfigurationOptions#header()}, respecting the rules of - * {@link FileConfigurationOptions#copyHeader()} if set. - * - * @return Compiled header - */ - @NotNull - protected abstract String buildHeader(); - - @NotNull - @Override - public FileConfigurationOptions options() { - if (options == null) { - options = new FileConfigurationOptions(this); - } - - return (FileConfigurationOptions) options; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfigurationOptions.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfigurationOptions.java deleted file mode 100644 index 48e126ea..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfigurationOptions.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import com.dumbdogdiner.stickyapi.common.configuration.MemoryConfiguration; -import com.dumbdogdiner.stickyapi.common.configuration.MemoryConfigurationOptions; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Various settings for controlling the input and output of a - * {@link FileConfiguration} - */ -public class FileConfigurationOptions extends MemoryConfigurationOptions { - private String header = null; - private boolean copyHeader = true; - - protected FileConfigurationOptions(@NotNull MemoryConfiguration configuration) { - super(configuration); - } - - @NotNull - @Override - public FileConfiguration configuration() { - return (FileConfiguration) super.configuration(); - } - - @NotNull - @Override - public FileConfigurationOptions copyDefaults(boolean value) { - super.copyDefaults(value); - return this; - } - - @NotNull - @Override - public FileConfigurationOptions pathSeparator(char value) { - super.pathSeparator(value); - return this; - } - - /** - * Gets the header that will be applied to the top of the saved output. - *

- * This header will be commented out and applied directly at the top of the - * generated output of the {@link FileConfiguration}. It is not required to - * include a newline at the end of the header as it will automatically be - * applied, but you may include one if you wish for extra spacing. - *

- * Null is a valid value which will indicate that no header is to be applied. - * The default value is null. - * - * @return Header - */ - @Nullable - public String header() { - return header; - } - - /** - * Sets the header that will be applied to the top of the saved output. - *

- * This header will be commented out and applied directly at the top of the - * generated output of the {@link FileConfiguration}. It is not required to - * include a newline at the end of the header as it will automatically be - * applied, but you may include one if you wish for extra spacing. - *

- * Null is a valid value which will indicate that no header is to be applied. - * - * @param value New header - * @return This object, for chaining - */ - @NotNull - public FileConfigurationOptions header(@Nullable String value) { - this.header = value; - return this; - } - - /** - * Gets whether or not the header should be copied from a default source. - *

- * If this is true, if a default {@link FileConfiguration} is passed to - * {@link FileConfiguration#setDefaults(com.dumbdogdiner.stickyapi.common.configuration.Configuration)} - * then upon saving it will use the header from that config, instead of the one - * provided here. - *

- * If no default is set on the configuration, or the default is not of type - * FileConfiguration, or that config has no header ({@link #header()} returns - * null) then the header specified in this configuration will be used. - *

- * Defaults to true. - * - * @return Whether or not to copy the header - */ - public boolean copyHeader() { - return copyHeader; - } - - /** - * Sets whether or not the header should be copied from a default source. - *

- * If this is true, if a default {@link FileConfiguration} is passed to - * {@link FileConfiguration#setDefaults(com.dumbdogdiner.stickyapi.common.configuration.Configuration)} - * then upon saving it will use the header from that config, instead of the one - * provided here. - *

- * If no default is set on the configuration, or the default is not of type - * FileConfiguration, or that config has no header ({@link #header()} returns - * null) then the header specified in this configuration will be used. - *

- * Defaults to true. - * - * @param value Whether or not to copy the header - * @return This object, for chaining - */ - @NotNull - public FileConfigurationOptions copyHeader(boolean value) { - copyHeader = value; - - return this; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfiguration.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfiguration.java deleted file mode 100644 index 5d5cfe27..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfiguration.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.Reader; -import java.util.Map; -import java.util.logging.Level; -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import com.dumbdogdiner.stickyapi.common.configuration.Configuration; -import com.dumbdogdiner.stickyapi.common.configuration.ConfigurationSection; -import com.dumbdogdiner.stickyapi.common.configuration.InvalidConfigurationException; -import org.jetbrains.annotations.NotNull; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.error.YAMLException; -import org.yaml.snakeyaml.representer.Representer; - -/** - * An implementation of {@link Configuration} which saves all files in Yaml. - * Note that this implementation is not synchronized. - */ -public class YamlConfiguration extends FileConfiguration { - protected static final String COMMENT_PREFIX = "# "; - protected static final String BLANK_CONFIG = "{}\n"; - private final DumperOptions yamlOptions = new DumperOptions(); - private final Representer yamlRepresenter = new YamlRepresenter(); - private final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions); - - @NotNull - @Override - public String saveToString() { - yamlOptions.setIndent(options().indent()); - yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - - String header = buildHeader(); - String dump = yaml.dump(getValues(false)); - - if (dump.equals(BLANK_CONFIG)) { - dump = ""; - } - - return header + dump; - } - - @Override - public void loadFromString(@NotNull String contents) throws InvalidConfigurationException { - Validate.notNull(contents, "Contents cannot be null"); - - Map input; - try { - input = (Map) yaml.load(contents); - } catch (YAMLException e) { - throw new InvalidConfigurationException(e); - } catch (ClassCastException e) { - throw new InvalidConfigurationException("Top level is not a Map."); - } - - String header = parseHeader(contents); - if (header.length() > 0) { - options().header(header); - } - - if (input != null) { - convertMapsToSections(input, this); - } - } - - protected void convertMapsToSections(@NotNull Map input, @NotNull ConfigurationSection section) { - for (Map.Entry entry : input.entrySet()) { - String key = entry.getKey().toString(); - Object value = entry.getValue(); - - if (value instanceof Map) { - convertMapsToSections((Map) value, section.createSection(key)); - } else { - section.set(key, value); - } - } - } - - @NotNull - protected String parseHeader(@NotNull String input) { - String[] lines = input.split("\r?\n", -1); - StringBuilder result = new StringBuilder(); - boolean readingHeader = true; - boolean foundHeader = false; - - for (int i = 0; (i < lines.length) && (readingHeader); i++) { - String line = lines[i]; - - if (line.startsWith(COMMENT_PREFIX)) { - if (i > 0) { - result.append("\n"); - } - - if (line.length() > COMMENT_PREFIX.length()) { - result.append(line.substring(COMMENT_PREFIX.length())); - } - - foundHeader = true; - } else if ((foundHeader) && (line.length() == 0)) { - result.append("\n"); - } else if (foundHeader) { - readingHeader = false; - } - } - - return result.toString(); - } - - @NotNull - @Override - protected String buildHeader() { - String header = options().header(); - - if (options().copyHeader()) { - Configuration def = getDefaults(); - - if ((def != null) && (def instanceof FileConfiguration)) { - FileConfiguration filedefaults = (FileConfiguration) def; - String defaultsHeader = filedefaults.buildHeader(); - - if ((defaultsHeader != null) && (defaultsHeader.length() > 0)) { - return defaultsHeader; - } - } - } - - if (header == null) { - return ""; - } - - StringBuilder builder = new StringBuilder(); - String[] lines = header.split("\r?\n", -1); - boolean startedHeader = false; - - for (int i = lines.length - 1; i >= 0; i--) { - builder.insert(0, "\n"); - - if ((startedHeader) || (lines[i].length() != 0)) { - builder.insert(0, lines[i]); - builder.insert(0, COMMENT_PREFIX); - startedHeader = true; - } - } - - return builder.toString(); - } - - @NotNull - @Override - public YamlConfigurationOptions options() { - if (options == null) { - options = new YamlConfigurationOptions(this); - } - - return (YamlConfigurationOptions) options; - } - - /** - * Creates a new {@link YamlConfiguration}, loading from the given file. - *

- * Any errors loading the Configuration will be logged and then ignored. If the - * specified input is not a valid config, a blank config will be returned. - *

- * The encoding used may follow the system dependent default. - * - * @param file Input file - * @return Resulting configuration - * @throws IllegalArgumentException Thrown if file is null - */ - @NotNull - public static YamlConfiguration loadConfiguration(@NotNull File file) { - Validate.notNull(file, "File cannot be null"); - - YamlConfiguration config = new YamlConfiguration(); - - try { - config.load(file); - } catch (FileNotFoundException ex) { - } catch (IOException ex) { - Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); - } catch (InvalidConfigurationException ex) { - Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); - } - - return config; - } - - /** - * Creates a new {@link YamlConfiguration}, loading from the given reader. - *

- * Any errors loading the Configuration will be logged and then ignored. If the - * specified input is not a valid config, a blank config will be returned. - * - * @param reader input - * @return resulting configuration - * @throws IllegalArgumentException Thrown if stream is null - */ - @NotNull - public static YamlConfiguration loadConfiguration(@NotNull Reader reader) { - Validate.notNull(reader, "Stream cannot be null"); - - YamlConfiguration config = new YamlConfiguration(); - - try { - config.load(reader); - } catch (IOException ex) { - Bukkit.getLogger().log(Level.SEVERE, "Cannot load configuration from stream", ex); - } catch (InvalidConfigurationException ex) { - Bukkit.getLogger().log(Level.SEVERE, "Cannot load configuration from stream", ex); - } - - return config; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfigurationOptions.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfigurationOptions.java deleted file mode 100644 index dcf6621f..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfigurationOptions.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import org.apache.commons.lang.Validate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Various settings for controlling the input and output of a - * {@link YamlConfiguration} - */ -public class YamlConfigurationOptions extends FileConfigurationOptions { - private int indent = 2; - - protected YamlConfigurationOptions(@NotNull YamlConfiguration configuration) { - super(configuration); - } - - @NotNull - @Override - public YamlConfiguration configuration() { - return (YamlConfiguration) super.configuration(); - } - - @NotNull - @Override - public YamlConfigurationOptions copyDefaults(boolean value) { - super.copyDefaults(value); - return this; - } - - @NotNull - @Override - public YamlConfigurationOptions pathSeparator(char value) { - super.pathSeparator(value); - return this; - } - - @NotNull - @Override - public YamlConfigurationOptions header(@Nullable String value) { - super.header(value); - return this; - } - - @NotNull - @Override - public YamlConfigurationOptions copyHeader(boolean value) { - super.copyHeader(value); - return this; - } - - /** - * Gets how much spaces should be used to indent each line. - *

- * The minimum value this may be is 2, and the maximum is 9. - * - * @return How much to indent by - */ - public int indent() { - return indent; - } - - /** - * Sets how much spaces should be used to indent each line. - *

- * The minimum value this may be is 2, and the maximum is 9. - * - * @param value New indent - * @return This object, for chaining - */ - @NotNull - public YamlConfigurationOptions indent(int value) { - Validate.isTrue(value >= 2, "Indent must be at least 2 characters"); - Validate.isTrue(value <= 9, "Indent cannot be greater than 9 characters"); - - this.indent = value; - return this; - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConstructor.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConstructor.java deleted file mode 100644 index 76c5e60e..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConstructor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import java.util.Map; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.yaml.snakeyaml.constructor.SafeConstructor; -import org.yaml.snakeyaml.error.YAMLException; -import org.yaml.snakeyaml.nodes.Node; -import org.yaml.snakeyaml.nodes.Tag; - -public class YamlConstructor extends SafeConstructor { - - public YamlConstructor() { - this.yamlConstructors.put(Tag.MAP, new ConstructCustomObject()); - } - - private class ConstructCustomObject extends ConstructYamlMap { - - @Nullable - @Override - public Object construct(@NotNull Node node) { - if (node.isTwoStepsConstruction()) { - throw new YAMLException("Unexpected referential mapping structure. Node: " + node); - } - - Map raw = (Map) super.construct(node); - - return raw; - } - - @Override - public void construct2ndStep(@NotNull Node node, @NotNull Object object) { - throw new YAMLException("Unexpected referential mapping structure. Node: " + node); - } - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlRepresenter.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlRepresenter.java deleted file mode 100644 index b4faf714..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlRepresenter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import java.util.LinkedHashMap; -import java.util.Map; -import com.dumbdogdiner.stickyapi.common.configuration.ConfigurationSection; -import com.dumbdogdiner.stickyapi.common.configuration.serialization.ConfigurationSerializable; -import org.jetbrains.annotations.NotNull; -import org.yaml.snakeyaml.nodes.Node; -import org.yaml.snakeyaml.representer.Representer; - -public class YamlRepresenter extends Representer { - - public YamlRepresenter() { - this.multiRepresenters.put(ConfigurationSection.class, new RepresentConfigurationSection()); - this.multiRepresenters.put(ConfigurationSerializable.class, new RepresentConfigurationSerializable()); - } - - private class RepresentConfigurationSection extends RepresentMap { - - @NotNull - @Override - public Node representData(@NotNull Object data) { - return super.representData(((ConfigurationSection) data).getValues(false)); - } - } - - private class RepresentConfigurationSerializable extends RepresentMap { - - @NotNull - @Override - public Node representData(@NotNull Object data) { - ConfigurationSerializable serializable = (ConfigurationSerializable) data; - Map values = new LinkedHashMap(); - values.putAll(serializable.serialize()); - - return super.representData(values); - } - } -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/package-info.java deleted file mode 100644 index 29ca3ac3..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -/** - * Classes dedicated to facilitating - * {@link com.dumbdogdiner.stickyapi.common.configuration.Configuration - * configurations} to be read and stored on the filesystem. - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/ConfigurationSerializable.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/ConfigurationSerializable.java deleted file mode 100644 index 34a25eab..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/ConfigurationSerializable.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.serialization; - -import java.util.Map; -import org.jetbrains.annotations.NotNull; - -/** - * Represents an object that may be serialized. - *

- * These objects MUST implement one of the following, in addition to the methods - * as defined by this interface: - *

- * - * @see DelegateDeserialization - * @see SerializableAs - */ -public interface ConfigurationSerializable { - - /** - * Creates a Map representation of this class. - *

- * This class must provide a method to restore this class, as defined in the - * {@link ConfigurationSerializable} interface javadocs. - * - * @return Map containing the current state of this class - */ - @NotNull - public Map serialize(); -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/DelegateDeserialization.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/DelegateDeserialization.java deleted file mode 100644 index effc6acf..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/DelegateDeserialization.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.serialization; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.jetbrains.annotations.NotNull; - -/** - * Applies to a {@link ConfigurationSerializable} that will delegate all - * deserialization to another {@link ConfigurationSerializable}. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface DelegateDeserialization { - /** - * Which class should be used as a delegate for this classes deserialization - * - * @return Delegate class - */ - @NotNull - public Class value(); -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/SerializableAs.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/SerializableAs.java deleted file mode 100644 index 870d87bc..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/SerializableAs.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.serialization; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.jetbrains.annotations.NotNull; - -/** - * Represents an "alias" that a {@link ConfigurationSerializable} may be stored - * as. If this is not present on a {@link ConfigurationSerializable} class, it - * will use the fully qualified name of the class. - *

- * This value will be stored in the configuration so that the configuration - * deserialization can determine what type it is. - *

- * Using this annotation on any other class than a - * {@link ConfigurationSerializable} will have no effect. - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface SerializableAs { - /** - * This is the name your class will be stored and retrieved as. - *

- * This name MUST be unique. We recommend using names such as "MyPluginThing" - * instead of "Thing". - * - * @return Name to serialize the class as. - */ - @NotNull - public String value(); -} diff --git a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/package-info.java b/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/package-info.java deleted file mode 100644 index 30735e7b..00000000 --- a/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -/** - * Classes dedicated to being able to perform serialization specialized for the - * Bukkit {@link com.dumbdogdiner.stickyapi.common.configuration.Configuration - * configuration} implementation. - */ -package com.dumbdogdiner.stickyapi.common.configuration.serialization;