This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.event;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.InvalidObjectException;
023import java.io.ObjectStreamException;
024import java.io.Serializable;
025import java.util.*;
026
027/**
028 * Event types define a hierarchical structure of events. Each event is bound to a certain event type.
029 * All event types have a super type, only the root event type {@link EventType#ROOT} has no super type.
030 *
031 * Event types should be stored as static fields on the events itself.
032 *
033 * @param <T> The type class parameter allows to define the types in a type safe way and represents a event class,
034 *           where the type is associated to.
035 */
036public class EventType<T extends Event> implements Serializable  {
037
038
039    public static final EventType<Event> ROOT = new EventType<>();
040
041    private final String name;
042    private final EventType<? super T> superType;
043    private WeakHashMap<EventType<? extends T>, Void> subTypes;
044
045    /**
046     * Creates a type with the given name and the root type as parent.
047     * @param name the name of the new type
048     */
049    public EventType(String name) {
050        this.superType = ROOT;
051        this.name = name;
052    }
053
054    /**
055     * Creates a event type instance with the given super type and name.
056     *
057     * @param superType The super type or <code>null</code>, if this is the root type.
058     * @param name
059     */
060    public EventType(EventType<? super T> superType, String name) {
061        if (superType==null) {
062            throw new NullPointerException("Super Type may not be null");
063        }
064        this.name = name;
065        this.superType = superType;
066        superType.register(this);
067    }
068
069    /**
070     * Creates the root type
071     */
072    private EventType() {
073        this.name="ROOT";
074        this.superType=null;
075    }
076
077    public String name() {
078        return name;
079    }
080
081    public EventType<? super T> getSuperType() {
082        return superType;
083    }
084
085    private void register(EventType<? extends T> subType) {
086        if (subTypes == null) {
087            subTypes = new WeakHashMap<>();
088        }
089        for (EventType<? extends T> t : subTypes.keySet()) {
090            if (((t.name == null && subType.name == null) || (t.name != null && t.name.equals(subType.name)))) {
091                throw new IllegalArgumentException("EventType \"" + subType + "\""
092                        + "with parent \"" + subType.getSuperType()+"\" already exists");
093            }
094        }
095        subTypes.put(subType, null);
096    }
097
098
099    public static List<EventType<?>> fetchSuperTypes(EventType<?> type) {
100        List<EventType<?>> typeList = new ArrayList<>();
101        EventType<?> cType = type;
102        while (cType!=null) {
103            typeList.add(cType);
104            cType = cType.getSuperType();
105        }
106        return typeList;
107    }
108
109    public static boolean isInstanceOf(EventType<?> type, EventType<?> baseType) {
110        EventType<?> cType = type;
111        while(cType!=null) {
112            if (cType == baseType) {
113                return true;
114            }
115            cType = cType.getSuperType();
116        }
117        return false;
118    }
119
120
121    private Object writeReplace() throws ObjectStreamException {
122        Deque<String> path = new LinkedList<String>();
123        EventType<?> t = this;
124        while (t != ROOT) {
125            path.addFirst(t.name);
126            t = t.superType;
127        }
128        return new EventTypeSerialization(new ArrayList<>(path));
129    }
130
131    static class EventTypeSerialization implements Serializable {
132        private static final long serialVersionUID = 1841649460281865547L;
133        private List<String> path;
134
135        public EventTypeSerialization(List<String> path) {
136            this.path = path;
137        }
138
139        private Object readResolve() throws ObjectStreamException {
140            EventType t = ROOT;
141            for (int i = 0; i < path.size(); ++i) {
142                String p = path.get(i);
143                if (t.subTypes != null) {
144                    EventType<?> s = findSubType(t.subTypes.keySet(), p);
145                    if (s == null) {
146                        throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")");
147                    }
148                    t = s;
149                } else {
150                    throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")");
151                }
152            }
153            return t;
154        }
155
156        private EventType<?> findSubType(Set<EventType> subTypes, String name) {
157            for (EventType t : subTypes) {
158                if (((t.name == null && name == null) || (t.name != null && t.name.equals(name)))) {
159                    return t;
160                }
161            }
162            return null;
163        }
164
165    }
166}