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 * @since 2.0
040 * @param <T> the event associated with this type
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 <b>null</b>, 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 <b>null</b>, result is <b>false</b>.
070     *
071     * @param derivedType the derived event type
072     * @param baseType the base event type
073     * @return <b>true</b> if the derived type is an instance of the base type, <b>false</b> 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 <b>null</b> 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}