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 1790899 2017-04-10 21:56:46Z 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(EventType<? super T> superEventType, 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(EventType<?> eventType)
122    {
123        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(EventType<?> derivedType,
145            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}