001/* 002 * GWTEventService 003 * Copyright (c) 2011 and beyond, strawbill UG (haftungsbeschr?nkt) 004 * 005 * This is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Lesser General Public License as 007 * published by the Free Software Foundation; either version 3 of 008 * the License, or (at your option) any later version. 009 * Other licensing for GWTEventService may also be possible on request. 010 * Please view the license.txt of the project for more information. 011 * 012 * This software is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this software; if not, write to the Free 019 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 020 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 021 */ 022package de.novanic.eventservice.service.registry.user; 023 024import de.novanic.eventservice.client.event.DomainEvent; 025import de.novanic.eventservice.client.event.Event; 026import de.novanic.eventservice.client.event.DefaultDomainEvent; 027import de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent; 028import de.novanic.eventservice.client.event.listener.unlisten.DefaultUnlistenEvent; 029import de.novanic.eventservice.client.event.filter.EventFilter; 030import de.novanic.eventservice.client.event.domain.Domain; 031import de.novanic.eventservice.util.PlatformUtil; 032 033import java.util.*; 034import java.util.concurrent.ConcurrentLinkedQueue; 035import java.util.concurrent.ConcurrentHashMap; 036 037/** 038 * UserInfo is a class to represent all users/clients and to manage all their information. 039 * It holds the events, the EventFilters ({@link de.novanic.eventservice.client.event.filter.EventFilter}) and the last 040 * activity time for the user. 041 * 042 * @author sstrohschein 043 * <br>Date: 19.01.2009 044 * <br>Time: 23:59:58 045 */ 046public class UserInfo implements Comparable<UserInfo> 047{ 048 private final String myUserId; 049 private final Queue<DomainEvent> myEvents; 050 private final Map<Domain, EventFilter> myDomainEventFilters; 051 private UnlistenEvent myUnlistenEvent; 052 private volatile long myLastActivityTime; 053 054 /** 055 * Creates a new UserInfo for the user id. 056 * @param aUserId user 057 */ 058 public UserInfo(String aUserId) { 059 myUserId = aUserId; 060 myEvents = new ConcurrentLinkedQueue<DomainEvent>(); 061 myDomainEventFilters = new ConcurrentHashMap<Domain, EventFilter>(); 062 myLastActivityTime = PlatformUtil.getCurrentTime(); 063 } 064 065 /** 066 * Returns the user id. 067 * @return user / user id 068 */ 069 public String getUserId() { 070 return myUserId; 071 } 072 073 /** 074 * Adds an event for a domain to the user. 075 * @param aDomain domain 076 * @param anEvent event 077 */ 078 public void addEvent(Domain aDomain, Event anEvent) { 079 DomainEvent theDomainEvent = new DefaultDomainEvent(anEvent, aDomain); 080 myEvents.add(theDomainEvent); 081 notifyEventListening(); 082 } 083 084 /** 085 * doNotifyAll informs all waiting Threads for new events. 086 */ 087 public synchronized void notifyEventListening() { 088 notifyAll(); 089 } 090 091 /** 092 * Returns and removes all recorded events. 093 * @param aMaxEvents maximum amount of events which should be processed (at once). 094 * The rest will be processed with the next call/request (again to the maximum amount, of course). 095 * The maximum amount of events prevents the logic from endless seeking of events (for example when more events are concurrently added than this logic/thread can process). 096 * @return all events according to the user 097 */ 098 public List<DomainEvent> retrieveEvents(int aMaxEvents) { 099 List<DomainEvent> theEventList = new ArrayList<DomainEvent>(myEvents.size()); 100 DomainEvent theEvent; 101 for(int i = 0; i < aMaxEvents && (theEvent = myEvents.poll()) != null; i++) { 102 theEventList.add(theEvent); 103 } 104 return theEventList; 105 } 106 107 /** 108 * Checks if events are available. 109 * @return true when no events recognized, otherwise false 110 */ 111 public boolean isEventsEmpty() { 112 return myEvents.isEmpty(); 113 } 114 115 /** 116 * Sets an EventFilter to a domain. 117 * @param aDomain domain where the EventFilter should be applied. 118 * @param anEventFilter EventFilter to filter the events for the domain 119 */ 120 public void setEventFilter(final Domain aDomain, EventFilter anEventFilter) { 121 if(anEventFilter != null) { 122 myDomainEventFilters.put(aDomain, anEventFilter); 123 } 124 } 125 126 /** 127 * Removes the EventFilter for a domain. 128 * @param aDomain domain where the EventFilter to remove is applied. 129 * @return true when the {@link de.novanic.eventservice.client.event.filter.EventFilter} is removed, otherwise false 130 * (for example the {@link de.novanic.eventservice.client.event.filter.EventFilter} was already removed before) 131 */ 132 public boolean removeEventFilter(final Domain aDomain) { 133 return aDomain != null && myDomainEventFilters.remove(aDomain) != null; 134 } 135 136 /** 137 * Returns the EventFilter for the domain. 138 * @param aDomain domain 139 * @return EventFilter for the domain 140 */ 141 public EventFilter getEventFilter(Domain aDomain) { 142 if(aDomain != null) { 143 return myDomainEventFilters.get(aDomain); 144 } 145 return null; 146 } 147 148 /** 149 * Returns the registered {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent}. That can be 150 * a custom {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} which can be set with 151 * {@link de.novanic.eventservice.service.registry.user.UserInfo#setUnlistenEvent(de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent)} 152 * or a default/generic {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} when no custom 153 * {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} is registered. 154 * @return {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} to report a timeout or 155 * a user/client which left a domain. 156 */ 157 public UnlistenEvent getUnlistenEvent() { 158 if(myUnlistenEvent == null) { 159 return new DefaultUnlistenEvent();//create here on request/unlisten to save memory 160 } 161 return myUnlistenEvent; 162 } 163 164 /** 165 * A custom {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} can be set which is transferred 166 * to all registered {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEventListener} instances when 167 * an unlisten occurred (for example by a timeout or when a user/client leaves a domain). When no custom 168 * {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} is registered, a default/generic 169 * {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} will be processed and reported. 170 * @param anUnlistenEvent {@link de.novanic.eventservice.client.event.listener.unlisten.UnlistenEvent} which should be 171 * triggered. 172 */ 173 public void setUnlistenEvent(UnlistenEvent anUnlistenEvent) { 174 myUnlistenEvent = anUnlistenEvent; 175 } 176 177 /** 178 * Sets the last activity time. The last activity is used to recognize timeouts. 179 * @param aLastActivityTime last activity time 180 */ 181 public void setLastActivityTime(long aLastActivityTime) { 182 myLastActivityTime = aLastActivityTime; 183 } 184 185 /** 186 * Returns the last activity time. The last activity is used to recognize timeouts. 187 * @return last activity time 188 */ 189 public long getLastActivityTime() { 190 return myLastActivityTime; 191 } 192 193 /** 194 * That method must be called to report a user activity and protects the user from a timeout for the time of the 195 * timeout interval ({@link de.novanic.eventservice.config.EventServiceConfiguration#getTimeoutTime()}). 196 */ 197 public void reportUserActivity() { 198 setLastActivityTime(PlatformUtil.getCurrentTime()); 199 } 200 201 public int compareTo(UserInfo aUserInfo) { 202 return myUserId.compareTo(aUserInfo.myUserId); 203 } 204 205 public boolean equals(Object anObject) { 206 if(this == anObject) { 207 return true; 208 } 209 if(anObject == null || getClass() != anObject.getClass()) { 210 return false; 211 } 212 UserInfo theOtherUserInfo = (UserInfo)anObject; 213 return myUserId.equals(theOtherUserInfo.myUserId); 214 } 215 216 public int hashCode() { 217 return myUserId.hashCode(); 218 } 219 220 /** 221 * The user id is used to represent the UserInfo. 222 * @return String representation (user id) of the UserInfo. 223 */ 224 public String toString() { 225 return getUserId(); 226 } 227}