    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 * @since 2.0
    044 * @param <T> the event associated with this type
    045 */
    046public class EventType<T extends Event> implements Serializable
    047{
    048    /** Serial version UID. */
    049    private static final long serialVersionUID = 20150416L;
    050
    051    /** Constant for the format used by toString(). */
    052    private static final String FMT_TO_STRING = "%s [ %s ]";
    053
    054    /** Stores the super type of this type. */
    055    private final EventType<? super T> superType;
    056
    057    /** A name for this event type. */
    058    private final String name;
    059
    060    /**
    061     * Creates a new instance of {@code EventType} and initializes it with the
    062     * super type and a type name. If no super type is specified, this is the
    063     * root event type.
    064     *
    065     * @param superEventType the super event type
    066     * @param typeName the name of this event type
    067     */
    068    public EventType(final EventType<? super T> superEventType, final String typeName)
    069    {
    070        superType = superEventType;
    071        name = typeName;
    072    }
    073
    074    /**
    075     * Returns the super event type. Result is <b>null</b> for the root event
    076     * type.
    077     *
    078     * @return the super event type
    079     */
    080    public EventType<? super T> getSuperType()
    081    {
    082        return superType;
    083    }
    084
    085    /**
    086     * Returns the name of this event type. The name has no specific semantic
    087     * meaning. It is just used for debugging purposes and also part of the
    088     * string representation of this event type.
    089     *
    090     * @return the event type name
    091     */
    092    public String getName()
    093    {
    094        return name;
    095    }
    096
    097    /**
    098     * Returns a string representation for this object. This method is mainly
    099     * overridden for debugging purposes. The returned string contains the name
    100     * of this event type.
    101     *
    102     * @return a string for this object
    103     */
    104    @Override
    105    public String toString()
    106    {
    107        return String.format(FMT_TO_STRING, getClass().getSimpleName(),
    108                getName());
    109    }
    110
    111    /**
    112     * Returns a set with all event types that are super types of the specified
    113     * type. This set contains the direct and indirect super types and also
    114     * includes the given type itself. The passed in type may be <b>null</b>,
    115     * then an empty set is returned.
    116     *
    117     * @param eventType the event type in question
    118     * @return a set with all super event types
    119     */
    120    public static Set<EventType<?>> fetchSuperEventTypes(final EventType<?> eventType)
    121    {
    122        final Set<EventType<?>> types = new HashSet<>();
    123        EventType<?> currentType = eventType;
    124        while (currentType != null)
    125        {
    126            types.add(currentType);
    127            currentType = currentType.getSuperType();
    128        }
    129        return types;
    130    }
    131
    132    /**
    133     * Checks whether an event type is derived from another type. This
    134     * implementation tests whether {@code baseType} is a direct or indirect
    135     * super type of {@code derivedType}. If one of the types is <b>null</b>,
    136     * result is <b>false</b>.
    137     *
    138     * @param derivedType the derived event type
    139     * @param baseType the base event type
    140     * @return <b>true</b> if the derived type is an instance of the base type,
    141     *         <b>false</b> otherwise
    142     */
    143    public static boolean isInstanceOf(final EventType<?> derivedType,
    144            final EventType<?> baseType)
    145    {
    146        EventType<?> currentType = derivedType;
    147        while (currentType != null)
    148        {
    149            if (currentType == baseType)
    150            {
    151                return true;
    152            }
    153            currentType = currentType.getSuperType();
    154        }
    155        return false;
    156    }
    157}