diff --git a/README.md b/README.md index f26197873..e001d2d4d 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,8 @@ aboutLibraries { // Full license text for license IDs mentioned here will be included, even if no detected dependency uses them. additionalLicenses = ["mit", "mpl_2_0"] // Allows to exclude some fields from the generated meta data field. - excludeFields = ["developers", "funding"] + // If the class name is specified, the field is only excluded for that class; without a class name, the exclusion is global. + excludeFields = ["License.name", "developers", "funding"] // Enable inclusion of `platform` dependencies in the library report includePlatform = true // Define the strict mode, will fail if the project uses licenses not allowed diff --git a/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/AboutLibrariesExtension.kt b/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/AboutLibrariesExtension.kt index 8eeb827be..50f293955 100644 --- a/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/AboutLibrariesExtension.kt +++ b/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/AboutLibrariesExtension.kt @@ -219,10 +219,14 @@ abstract class AboutLibrariesExtension { /** * Defines fields which will be excluded during the serialisation of the metadata output file. * - * Any field as included in the [com.mikepenz.aboutlibraries.plugin.mapping.Library] can theoretically be excluded. + * It is possible to qualify the field names by specifying the class name (e.g. "License.name"). + * Permissible qualifiers are "ResultContainer", "Library", "Developer", "Organization", "Funding", "Scm", + * "License" and "MetaData". + * Unqualified field names (e.g. "description") are applied to the entire output. + * * ``` * aboutLibraries { - * excludeFields = arrayOf("description", "tag") + * excludeFields = arrayOf("License.name", "ResultContainer.metadata", "description", "tag") * } * ``` */ diff --git a/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/model/ResultContainer.kt b/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/model/ResultContainer.kt index a86503e5f..d9d529e68 100644 --- a/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/model/ResultContainer.kt +++ b/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/model/ResultContainer.kt @@ -1,7 +1,12 @@ package com.mikepenz.aboutlibraries.plugin.model +import com.mikepenz.aboutlibraries.plugin.mapping.Developer +import com.mikepenz.aboutlibraries.plugin.mapping.Funding import com.mikepenz.aboutlibraries.plugin.mapping.Library import com.mikepenz.aboutlibraries.plugin.mapping.License +import com.mikepenz.aboutlibraries.plugin.mapping.Organization +import com.mikepenz.aboutlibraries.plugin.mapping.Scm +import com.mikepenz.aboutlibraries.plugin.util.PartialObjectConverter import groovy.json.JsonGenerator import groovy.json.JsonOutput import java.io.File @@ -26,10 +31,35 @@ class MetaData( ) fun ResultContainer.writeToDisk(outputFile: File, excludeFields: Array, prettyPrint: Boolean) { - val fieldNames = mutableListOf("artifactId", "groupId", "artifactFolder").also { - it.addAll(excludeFields) + val allowedExclusionQualifiers = setOf( + ResultContainer::class.simpleName, + Library::class.simpleName, + Developer::class.simpleName, + Organization::class.simpleName, + Funding::class.simpleName, + Scm::class.simpleName, + License::class.simpleName, + MetaData::class.simpleName, + ) + val excludedQualifiedFieldNames = mutableSetOf( + "${Library::class.simpleName}.${Library::artifactId.name}", + "${Library::class.simpleName}.${Library::groupId.name}", + "${Library::class.simpleName}.${Library::artifactFolder.name}" + ) + val excludedUnqualifiedFieldNames = mutableSetOf() + excludeFields.forEach { excludedField -> + val segments = excludedField.split(".") + if (segments.size == 2 && allowedExclusionQualifiers.contains(segments.first())) { + excludedQualifiedFieldNames.add(excludedField) + } else { + excludedUnqualifiedFieldNames.add(excludedField) + } } - val jsonGenerator = JsonGenerator.Options().excludeNulls().excludeFieldsByName(fieldNames).build() + val jsonGenerator = JsonGenerator.Options() + .excludeNulls() + .excludeFieldsByName(excludedUnqualifiedFieldNames) + .addConverter(PartialObjectConverter(excludedQualifiedFieldNames)) + .build() PrintWriter(OutputStreamWriter(outputFile.outputStream(), StandardCharsets.UTF_8), true).use { it.write(jsonGenerator.toJson(this).let { json -> if (prettyPrint) JsonOutput.prettyPrint(json) else json }) } diff --git a/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/util/PartialObjectConverter.kt b/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/util/PartialObjectConverter.kt new file mode 100644 index 000000000..5daf0edd1 --- /dev/null +++ b/plugin-build/plugin/src/main/kotlin/com/mikepenz/aboutlibraries/plugin/util/PartialObjectConverter.kt @@ -0,0 +1,33 @@ +package com.mikepenz.aboutlibraries.plugin.util + +import groovy.json.DefaultJsonGenerator +import groovy.json.JsonGenerator +import org.codehaus.groovy.runtime.DefaultGroovyMethods + +/** + * A converter for [JsonGenerator], which allows properties to be excluded from the output. + * The way it works is identical to the serialization of objects in [DefaultJsonGenerator]. + * @property excludedQualifiedPropertyNames The qualified name (class name + property name) + * of the properties that should be excluded from serialization. + */ +class PartialObjectConverter( + private val excludedQualifiedPropertyNames: Set +) : JsonGenerator.Converter { + + private val targetClassNames: Set = excludedQualifiedPropertyNames.mapTo(mutableSetOf()) { field -> + field.substringBeforeLast('.') + } + + private val excludedPropertyNames = setOf("class", "declaringClass", "metaClass") + + override fun handles(type: Class<*>?): Boolean { + return type != null && targetClassNames.contains(type.simpleName) + } + + override fun convert(value: Any, key: String?): Any { + return DefaultGroovyMethods.getProperties(value).filterKeys { propertyName -> + propertyName !in excludedPropertyNames && "${value::class.simpleName}.$propertyName" !in excludedQualifiedPropertyNames + } + } + +} \ No newline at end of file