    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 type. The event type can be used to
    029 * determine the meaning of a specific event. It also acts as filter criterion when event listeners are registered. The
    030 * listener is then called only for events of this type or derived types. The events in this library form a natural
    031 * hierarchy with base types and more specialized types. By specifying an appropriate event type at listener
    032 * registration time, it can be determined on a fine-granular basis which events are propagated to the listener.
    033 * </p>
    034 * <p>
    035 * Note: Users familiar with JavaFX probably recognize this approach to event handling. It allows for generic event
    036 * listener interfaces and a natural selection of events to be processed.
    037 * </p>
    038 *
    039 * @param <T> the event associated with this type
    040 * @since 2.0
    041 */
    042public class EventType<T extends Event> implements Serializable {
    043    /** Serial version UID. */
    044    private static final long serialVersionUID = 20150416L;
    045
    046    /** Constant for the format used by toString(). */
    047    private static final String FMT_TO_STRING = "%s [ %s ]";
    048
    049    /**
    050     * Returns a set with all event types that are super types of the specified type. This set contains the direct and
    051     * indirect super types and also includes the given type itself. The passed in type may be <strong>null</strong>, then an empty
    052     * set is returned.
    053     *
    054     * @param eventType the event type in question
    055     * @return a set with all super event types
    056     */
    057    public static Set<EventType<?>> fetchSuperEventTypes(final EventType<?> eventType) {
    058        final Set<EventType<?>> types = new HashSet<>();
    059        EventType<?> currentType = eventType;
    060        while (currentType != null) {
    061            types.add(currentType);
    062            currentType = currentType.getSuperType();
    063        }
    064        return types;
    065    }
    066
    067    /**
    068     * Checks whether an event type is derived from another type. This implementation tests whether {@code baseType} is a
    069     * direct or indirect super type of {@code derivedType}. If one of the types is <strong>null</strong>, result is <strong>false</strong>.
    070     *
    071     * @param derivedType the derived event type
    072     * @param baseType the base event type
    073     * @return <strong>true</strong> if the derived type is an instance of the base type, <strong>false</strong> otherwise
    074     */
    075    public static boolean isInstanceOf(final EventType<?> derivedType, final EventType<?> baseType) {
    076        EventType<?> currentType = derivedType;
    077        while (currentType != null) {
    078            if (currentType == baseType) {
    079                return true;
    080            }
    081            currentType = currentType.getSuperType();
    082        }
    083        return false;
    084    }
    085
    086    /** Stores the super type of this type. */
    087    private final EventType<? super T> superType;
    088
    089    /** A name for this event type. */
    090    private final String name;
    091
    092    /**
    093     * Creates a new instance of {@code EventType} and initializes it with the super type and a type name. If no super type
    094     * is specified, this is the root event type.
    095     *
    096     * @param superEventType the super event type
    097     * @param typeName the name of this event type
    098     */
    099    public EventType(final EventType<? super T> superEventType, final String typeName) {
    100        superType = superEventType;
    101        name = typeName;
    102    }
    103
    104    /**
    105     * Gets the name of this event type. The name has no specific semantic meaning. It is just used for debugging
    106     * purposes and also part of the string representation of this event type.
    107     *
    108     * @return the event type name
    109     */
    110    public String getName() {
    111        return name;
    112    }
    113
    114    /**
    115     * Gets the super event type. Result is <strong>null</strong> for the root event type.
    116     *
    117     * @return the super event type
    118     */
    119    public EventType<? super T> getSuperType() {
    120        return superType;
    121    }
    122
    123    /**
    124     * Returns a string representation for this object. This method is mainly overridden for debugging purposes. The
    125     * returned string contains the name of this event type.
    126     *
    127     * @return a string for this object
    128     */
    129    @Override
    130    public String toString() {
    131        return String.format(FMT_TO_STRING, getClass().getSimpleName(), getName());
    132    }
    133}