Class InheritanceSelector<T>

  • Type Parameters:
    T - the type of the objects handled by this selector
    All Implemented Interfaces:
    ExtensionPoint, Serializable
    Direct Known Subclasses:
    ParameterSelector

    public abstract class InheritanceSelector<T>
    extends Object
    implements Serializable, ExtensionPoint
    Extension point that allows other plugins to decide how a particular type of object should be treated during inheritance.

    During inheritance, the settings of multiple projects need to be merged into one object, since the leaf project needs to respond to Jenkins as if it did not do any inheritance.

    For example, a project might inherit multiple SCM objects, but it has to be ensured that only one is returned to Jenkins. The default behaviour in that case is to use SCM that was defined "last". If you want to override that behaviour, just register a new subclass of InheritanceSelector that has SCM as the template type and returns a mode other than InheritanceSelector.MODE.NOT_RESPONSIBLE fpr SCM in getModeFor(Class).

    Author:
    Martin Schroeder
    See Also:
    Serialized Form
    • Constructor Detail

      • InheritanceSelector

        public InheritanceSelector()
    • Method Detail

      • isApplicableFor

        public abstract boolean isApplicableFor​(Class<?> clazz)
        This method must return true, if the given Class is a valid supertype of the generic class used by your type.

        For example, if your selector handles a specific JobProperty, this method must return true if you encounter a JobProperty.

        This is used to do a fast pre-selection of which selectors to consider for the basic types offered by Jenkins (Properties, BuildSteps, Publishers, etc. pp.).

        Expect to see lots of ClassCastExceptions or your code not even being called, if you violate this.

        Parameters:
        clazz - the type of objects to check
        Returns:
        true, if this selector applies to the given type of objects.
      • getModeFor

        public abstract InheritanceSelector.MODE getModeFor​(Class<?> clazz)
        This method decides which mode should be used for the given class, if your selector supports that type at all!

        The latter part is essential, since returning anything other than InheritanceSelector.MODE.NOT_RESPONSIBLE for a type that your selector can't handle will result in ClassCastException or broken inheritance.

        The default mode if no selector is matches is InheritanceSelector.MODE.USE_LAST, meaning that the last object overwrites and hides all the others defined earlier.

        Parameters:
        clazz - the class of elements under inspection
        Returns:
        how to handle lists containing these elements
      • getObjectIdentifier

        public abstract String getObjectIdentifier​(T obj)
        This method returns an identifier for the given object. The identifier should be unique, as long as the objects are not the same in terms of inheritance. If they are the same their ID must also be the same.

        One example is parameters. If you have two objects for the parameter with the name "foo", they should get the same ID, because they logically define the same element in terms of inheritance and thus should either be merged or override each other.

        The purpose of this function is that candidates for merges can be identified by looping once through the list and then merging them in pairs or simply selection the last occurring one.

        Parameters:
        obj - the object that should be identified.
        Returns:
        an ID that is the same for multiple objects, if they define the same logical entity in terms of inheritance. Otherwise, the ID must be unique - or null, if this selector is not responsible for this object type.
      • merge

        public abstract T merge​(T prior,
                                T latter,
                                InheritanceProject caller)
        This function is called when isApplicableFor(Class) returned the InheritanceSelector.MODE.MERGE mode and the two objects have the same ID as returned by getObjectIdentifier(Object).

        It is expected of this function to merge the two objects together. This may or may not create a new object, but should not modify the two given objects.

        Do note that this function is only called, if there are at least 2 elements to merge. If any post-processing or singleton-handling is necessary, use handleSingleton(Object, InheritanceProject).

        Parameters:
        prior - the earlier defined object
        latter - the later defined object
        caller - the job for which the merge is done
        Returns:
        a merged instance. Maybe be new, or one of the input elements
      • handleSingleton

        public abstract T handleSingleton​(T object,
                                          InheritanceProject caller)
        This function will be called with the final object that was selected to be returned to Jenkins during application of this selector. Thus, its chief purpose is post-processing after all merges have been done.

        Please do note that if the InheritanceSelector.MODE.MULTIPLE was used; this function will be called for each occurrence.

        Parameters:
        object - the object selected to be returned to Jenkins.
        caller - the project for which the inheritance is determined.
        Returns:
        the object that should actually be returned to Jenkins. Do note that it may be part of a list, in which case the returned value replaces the original value.
      • applyAgainstList

        public final List<T> applyAgainstList​(List<T> lst,
                                              InheritanceProject caller)
        This method scans through the given List and filters/merges the elements based on the instructions that the subclass delivers.

        It expects that the entries in the list are sorted according to their inheritance-order; with later entries overwriting earlier settings.

        Based on the InheritanceSelector.MODE returned by the superclass, entries might be merged. In that case, the newly generated, merged entry is put at the location of the last occurrence.

        Parameters:
        lst - the list to scan for entries
        caller - the project that called the modification; can be necessary to correctly process certain operations.
        Returns:
        a new Deque that contains the filtered elements in inheritance-order.
        See Also:
        merge(Object, Object, InheritanceProject)