All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.pixee.maven.operator.Chain.kt Maven / Gradle / Ivy

package io.github.pixee.maven.operator

import org.slf4j.Logger
import org.slf4j.LoggerFactory

/**
 * Implements a Chain of Responsibility Pattern
 *
 * @constructor commands: Commands to Use
 */
class Chain(vararg commands: Command) {
    /**
     * Internal ArrayList of the Commands
     */
    internal val commandList: MutableList = ArrayList(commands.toList())

    /**
     * Executes the Commands in the Chain of Responsibility
     *
     * @param c ProjectModel (context)
     * @return Boolean if successful
     */
    fun execute(c: ProjectModel): Boolean {
        var done = false
        val listIterator = commandList.listIterator()

        while ((!done) && listIterator.hasNext()) {
            val nextCommand = listIterator.next()

            done = nextCommand.execute(c)

            if (done) {
                if (c.queryType == QueryType.NONE && (nextCommand !is SupportCommand)) {
                    c.modifiedByCommand = true
                }

                c.finishedByClass = nextCommand.javaClass.name

                break
            }
        }

        val result = done

        /**
         * Goes Reverse Order applying the filter pattern
         */

        while (listIterator.previousIndex() > 0) {
            val nextCommand = listIterator.previous()

            done = nextCommand.postProcess(c)

            if (done)
                break
        }

        return result
    }


    companion object {
        private val LOGGER: Logger = LoggerFactory.getLogger(Chain::class.java)

        /**
         * Returns a Pre-Configured Chain with the Defaults for Modifying a POM
         */
        fun createForModify() =
            Chain(
                CheckDependencyPresent,
                CheckParentPackaging,
                FormatCommand(),
                DiscardFormatCommand(),
                CompositeDependencyManagement(),
                SimpleUpgrade,
                SimpleDependencyManagement,
                SimpleInsert
            )

        private fun filterByQueryType(
            commandList: List>,
            queryType: QueryType,
            initialCommands: List = emptyList(),
            queryTypeFilter: ((queryType: QueryType) -> Boolean)
        ): Chain {
            val filteredCommands: List = commandList
                .filter { queryTypeFilter(it.first) }.mapNotNull {
                    val commandClassName = "io.github.pixee.maven.operator.${it.second}"

                    try {
                        Class.forName(commandClassName).newInstance() as Command
                    } catch (e: Throwable) {
                        LOGGER.warn("Creating class '{}': ", commandClassName, e)

                        null
                    }
                }
                .toList()

            val commands: List = initialCommands + filteredCommands

            if (commands.isEmpty())
                throw IllegalStateException("Unable to load any available strategy for ${queryType.name}")

            return Chain(*commands.toTypedArray())
        }

        /**
         * Some classes won't have all available dependencies on the classpath during runtime
         * for this reason we'll use 
Class.forName
and report issues creating */ val AVAILABLE_DEPENDENCY_QUERY_COMMANDS = listOf>( QueryType.SAFE to "QueryByResolver", QueryType.SAFE to "QueryByParsing", QueryType.UNSAFE to "QueryByEmbedder", QueryType.UNSAFE to "QueryByInvoker", ) /** * returns a pre-configured chain with the defaults for Dependency Querying */ fun createForDependencyQuery(queryType: QueryType = QueryType.SAFE): Chain = filterByQueryType( AVAILABLE_DEPENDENCY_QUERY_COMMANDS, queryType, listOf(CHECK_PARENT_DIR_COMMAND), { it == queryType } ) /** * List of Commands for Version Query */ val AVAILABLE_QUERY_VERSION_COMMANDS = listOf>( QueryType.NONE to "UnwrapEffectivePom", QueryType.SAFE to "VersionByCompilerDefinition", QueryType.SAFE to "VersionByProperty", ) /** * returns a pre-configured chain for Version Query */ fun createForVersionQuery(queryType: QueryType = QueryType.SAFE): Chain = filterByQueryType( AVAILABLE_QUERY_VERSION_COMMANDS, queryType, emptyList(), { it.ordinal <= queryType.ordinal } ) } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy