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

org.opalj.br.analyses.ProjectInformationKey.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br
package analyses

import java.util.concurrent.atomic.AtomicInteger

/**
 * `ProjectInformationKey` objects are used to get/associate some
 * (immutable) information with a project that should be computed on demand.
 * For example, imagine that you write an analysis that requires – as a foundation –
 * the project's call graph. In this case, to get the call graph it is sufficient
 * to pass the respective key to the [[Project]] object. If the call graph was already
 * computed that one will be returned, otherwise the computation will be performed and
 * the result will be cached for future usage before it is returned.
 *
 * ==Using Project Information==
 * If access to some project information is required, it is sufficient to use
 * the (singleton) instance of the respective `ProjectInformationKey` to get
 * the respective project information.
 *
 * For example, let's assume that an index of all fields and methods is needed. In this case the
 * code to get the index would be:
 * {{{
 * import ...{ProjectIndex,ProjectIndexKey}
 * val project : Project = ???
 * val projectIndex = project.get(ProjectIndexKey)
 * // do something with the index
 * }}}
 *
 * ==Providing Project Information/Implementing `ProjectInformationKey` ==
 * Making project wide information available on demand is done as follows.
 *
 *  1. Implement the base analysis that computes the information given some project.
 *  1. Implement your `ProjectInformationKey` class that inherits from this trait and
 *    which calls the base analysis. It is recommended that the factory method ([[compute]])
 *    is side-effect free.
 *
 * ===Threading===
 * [[Project]] takes care of threading related issues. The methods [[requirements]]
 * and [[compute]] will never be called concurrently w.r.t. the same `project` object.
 * However, concurrent calls may happen w.r.t. two different project objects.
 *
 * ===Caching===
 * [[Project]] takes care of the caching of the result of the computation of the
 * information.
 *
 * @tparam T The type of the information object that is derived.
 * @tparam I The type of information used at initialization time.
 *
 * @author Michael Eichberg
 */
trait ProjectInformationKey[T <: AnyRef, I <: AnyRef] {

    /**
     * The unique id of this key. The key is used to enable efficient access and
     * is automatically assigned by OPAL and will not change after that.
     */
    final val uniqueId: Int = ProjectInformationKey.nextId

    /**
     * Returns the information which other project information need to be available
     * before this analysis can be performed.
     *
     * If the analysis has no special requirements `Nil` can be returned.
     *
     * @note   '''All requirements must be listed; failing to specify a requirement can
     *         result in a deadlock.'''
     *
     * @note   Classes/Objects that implement this trait should not make the method `public`
     *         to avoid that this method is called accidentally by regular user code.
     */
    /*ABSTRACT*/ def requirements(project: SomeProject): ProjectInformationKeys

    /**
     * Computes the information for the given project.
     *
     * @note Classes that inherit from this trait are ''not'' expected to
     *      make this method public. This method is only expected to be called
     *      by an instance of a `Project`.
     */
    /*ABSTRACT*/ def compute(project: SomeProject): T

}

/**
 * Private companion object of ProjectInformationKey that is required to associate
 * project information objects with unique ids.
 *
 * @author Michael Eichberg
 */
private object ProjectInformationKey {

    private[this] val idGenerator = new AtomicInteger(0)

    private[ProjectInformationKey] def nextId: Int = idGenerator.getAndIncrement()

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy