    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.configuration2.event;
    018
    019import java.io.Serializable;
    020import java.util.HashSet;
    021import java.util.Set;
    022
    023/**
    024 * <p>
    025 * A class representing an event type.
    026 * </p>
    027 * <p>
    028 * The events produced by <em>Commons Configuration</em> all have a specific
    029 * type. The event type can be used to determine the meaning of a specific
    030 * event. It also acts as filter criterion when event listeners are registered.
    031 * The listener is then called only for events of this type or derived types.
    032 * The events in this library form a natural hierarchy with base types and more
    033 * specialized types. By specifying an appropriate event type at listener
    034 * registration time, it can be determined on a fine-granular basis which events
    035 * are propagated to the listener.
    036 * </p>
    037 * <p>
    038 * Note: Users familiar with JavaFX probably recognize this approach to event
    039 * handling. It allows for generic event listener interfaces and a natural
    040 * selection of events to be processed.
    041 * </p>
    042 *
    043 * @version $Id: EventType.java 1842194 2018-09-27 22:24:23Z ggregory $
    044 * @since 2.0
    045 * @param <T> the event associated with this type
    046 */
    047public class EventType<T extends Event> implements Serializable
    048{
    049    /** Serial version UID. */
    050    private static final long serialVersionUID = 20150416L;
    051
    052    /** Constant for the format used by toString(). */
    053    private static final String FMT_TO_STRING = "%s [ %s ]";
    054
    055    /** Stores the super type of this type. */
    056    private final EventType<? super T> superType;
    057
    058    /** A name for this event type. */
    059    private final String name;
    060
    061    /**
    062     * Creates a new instance of {@code EventType} and initializes it with the
    063     * super type and a type name. If no super type is specified, this is the
    064     * root event type.
    065     *
    066     * @param superEventType the super event type
    067     * @param typeName the name of this event type
    068     */
    069    public EventType(final EventType<? super T> superEventType, final String typeName)
    070    {
    071        superType = superEventType;
    072        name = typeName;
    073    }
    074
    075    /**
    076     * Returns the super event type. Result is <b>null</b> for the root event
    077     * type.
    078     *
    079     * @return the super event type
    080     */
    081    public EventType<? super T> getSuperType()
    082    {
    083        return superType;
    084    }
    085
    086    /**
    087     * Returns the name of this event type. The name has no specific semantic
    088     * meaning. It is just used for debugging purposes and also part of the
    089     * string representation of this event type.
    090     *
    091     * @return the event type name
    092     */
    093    public String getName()
    094    {
    095        return name;
    096    }
    097
    098    /**
    099     * Returns a string representation for this object. This method is mainly
    100     * overridden for debugging purposes. The returned string contains the name
    101     * of this event type.
    102     *
    103     * @return a string for this object
    104     */
    105    @Override
    106    public String toString()
    107    {
    108        return String.format(FMT_TO_STRING, getClass().getSimpleName(),
    109                getName());
    110    }
    111
    112    /**
    113     * Returns a set with all event types that are super types of the specified
    114     * type. This set contains the direct and indirect super types and also
    115     * includes the given type itself. The passed in type may be <b>null</b>,
    116     * then an empty set is returned.
    117     *
    118     * @param eventType the event type in question
    119     * @return a set with all super event types
    120     */
    121    public static Set<EventType<?>> fetchSuperEventTypes(final EventType<?> eventType)
    122    {
    123        final Set<EventType<?>> types = new HashSet<>();
    124        EventType<?> currentType = eventType;
    125        while (currentType != null)
    126        {
    127            types.add(currentType);
    128            currentType = currentType.getSuperType();
    129        }
    130        return types;
    131    }
    132
    133    /**
    134     * Checks whether an event type is derived from another type. This
    135     * implementation tests whether {@code baseType} is a direct or indirect
    136     * super type of {@code derivedType}. If one of the types is <b>null</b>,
    137     * result is <b>false</b>.
    138     *
    139     * @param derivedType the derived event type
    140     * @param baseType the base event type
    141     * @return <b>true</b> if the derived type is an instance of the base type,
    142     *         <b>false</b> otherwise
    143     */
    144    public static boolean isInstanceOf(final EventType<?> derivedType,
    145            final EventType<?> baseType)
    146    {
    147        EventType<?> currentType = derivedType;
    148        while (currentType != null)
    149        {
    150            if (currentType == baseType)
    151            {
    152                return true;
    153            }
    154            currentType = currentType.getSuperType();
    155        }
    156        return false;
    157    }
    158}