Fixed Checkstyle errors.
This commit is contained in:
		| @@ -50,6 +50,11 @@ public class App { | |||||||
|  |  | ||||||
|   boolean interactiveMode = false; |   boolean interactiveMode = false; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Program entry point. | ||||||
|  |    * | ||||||
|  |    * @param args command line args | ||||||
|  |    */ | ||||||
|   public static void main(String[] args) { |   public static void main(String[] args) { | ||||||
|     App app = new App(); |     App app = new App(); | ||||||
|  |  | ||||||
| @@ -71,6 +76,7 @@ public class App { | |||||||
|       try { |       try { | ||||||
|         prop.load(inputStream); |         prop.load(inputStream); | ||||||
|       } catch (IOException e) { |       } catch (IOException e) { | ||||||
|  |         System.out.println(propFileName + " was not found. Defaulting to non-interactive mode."); | ||||||
|       } |       } | ||||||
|       String property = prop.getProperty("INTERACTIVE_MODE"); |       String property = prop.getProperty("INTERACTIVE_MODE"); | ||||||
|       if (property.equalsIgnoreCase("YES")) { |       if (property.equalsIgnoreCase("YES")) { | ||||||
| @@ -79,6 +85,9 @@ public class App { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Run program in either interactive mode or not. | ||||||
|  |    */ | ||||||
|   public void run() { |   public void run() { | ||||||
|     if (interactiveMode) { |     if (interactiveMode) { | ||||||
|       runInteractiveMode(); |       runInteractiveMode(); | ||||||
| @@ -87,29 +96,32 @@ public class App { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Run program in non-interactive mode. | ||||||
|  |    */ | ||||||
|   public void quickRun() { |   public void quickRun() { | ||||||
|     EventManager eventManager = new EventManager(); |     EventManager eventManager = new EventManager(); | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|       // Create an Asynchronous event. |       // Create an Asynchronous event. | ||||||
|       int aEventID = eventManager.createAsyncEvent(60); |       int aEventId = eventManager.createAsyncEvent(60); | ||||||
|       System.out.println("Event [" + aEventID + "] has been created."); |       System.out.println("Event [" + aEventId + "] has been created."); | ||||||
|       eventManager.startEvent(aEventID); |       eventManager.startEvent(aEventId); | ||||||
|       System.out.println("Event [" + aEventID + "] has been started."); |       System.out.println("Event [" + aEventId + "] has been started."); | ||||||
|  |  | ||||||
|       // Create a Synchronous event. |       // Create a Synchronous event. | ||||||
|       int sEventID = eventManager.createSyncEvent(60); |       int sEventId = eventManager.createSyncEvent(60); | ||||||
|       System.out.println("Event [" + sEventID + "] has been created."); |       System.out.println("Event [" + sEventId + "] has been created."); | ||||||
|       eventManager.startEvent(sEventID); |       eventManager.startEvent(sEventId); | ||||||
|       System.out.println("Event [" + sEventID + "] has been started."); |       System.out.println("Event [" + sEventId + "] has been started."); | ||||||
|  |  | ||||||
|       eventManager.getStatus(aEventID); |       eventManager.getStatus(aEventId); | ||||||
|       eventManager.getStatus(sEventID); |       eventManager.getStatus(sEventId); | ||||||
|  |  | ||||||
|       eventManager.stopEvent(aEventID); |       eventManager.stopEvent(aEventId); | ||||||
|       System.out.println("Event [" + aEventID + "] has been stopped."); |       System.out.println("Event [" + aEventId + "] has been stopped."); | ||||||
|       eventManager.stopEvent(sEventID); |       eventManager.stopEvent(sEventId); | ||||||
|       System.out.println("Event [" + sEventID + "] has been stopped."); |       System.out.println("Event [" + sEventId + "] has been stopped."); | ||||||
|  |  | ||||||
|     } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException |     } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException | ||||||
|         | InvalidOperationException e) { |         | InvalidOperationException e) { | ||||||
| @@ -117,6 +129,9 @@ public class App { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Run program in interactive mode. | ||||||
|  |    */ | ||||||
|   public void runInteractiveMode() { |   public void runInteractiveMode() { | ||||||
|     EventManager eventManager = new EventManager(); |     EventManager eventManager = new EventManager(); | ||||||
|  |  | ||||||
| @@ -137,19 +152,19 @@ public class App { | |||||||
|         int eventTime = s.nextInt(); |         int eventTime = s.nextInt(); | ||||||
|         if (eventType.equalsIgnoreCase("A")) { |         if (eventType.equalsIgnoreCase("A")) { | ||||||
|           try { |           try { | ||||||
|             int eventID = eventManager.createAsyncEvent(eventTime); |             int eventId = eventManager.createAsyncEvent(eventTime); | ||||||
|             System.out.println("Event [" + eventID + "] has been created."); |             System.out.println("Event [" + eventId + "] has been created."); | ||||||
|             eventManager.startEvent(eventID); |             eventManager.startEvent(eventId); | ||||||
|             System.out.println("Event [" + eventID + "] has been started."); |             System.out.println("Event [" + eventId + "] has been started."); | ||||||
|           } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { |           } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { | ||||||
|             System.out.println(e.getMessage()); |             System.out.println(e.getMessage()); | ||||||
|           } |           } | ||||||
|         } else if (eventType.equalsIgnoreCase("S")) { |         } else if (eventType.equalsIgnoreCase("S")) { | ||||||
|           try { |           try { | ||||||
|             int eventID = eventManager.createSyncEvent(eventTime); |             int eventId = eventManager.createSyncEvent(eventTime); | ||||||
|             System.out.println("Event [" + eventID + "] has been created."); |             System.out.println("Event [" + eventId + "] has been created."); | ||||||
|             eventManager.startEvent(eventID); |             eventManager.startEvent(eventId); | ||||||
|             System.out.println("Event [" + eventID + "] has been started."); |             System.out.println("Event [" + eventId + "] has been started."); | ||||||
|           } catch (MaxNumOfEventsAllowedException | InvalidOperationException | LongRunningEventException |           } catch (MaxNumOfEventsAllowedException | InvalidOperationException | LongRunningEventException | ||||||
|               | EventDoesNotExistException e) { |               | EventDoesNotExistException e) { | ||||||
|             System.out.println(e.getMessage()); |             System.out.println(e.getMessage()); | ||||||
| @@ -159,18 +174,18 @@ public class App { | |||||||
|         } |         } | ||||||
|       } else if (option == 2) { |       } else if (option == 2) { | ||||||
|         System.out.print("Event ID: "); |         System.out.print("Event ID: "); | ||||||
|         int eventID = s.nextInt(); |         int eventId = s.nextInt(); | ||||||
|         try { |         try { | ||||||
|           eventManager.stopEvent(eventID); |           eventManager.stopEvent(eventId); | ||||||
|           System.out.println("Event [" + eventID + "] has been stopped."); |           System.out.println("Event [" + eventId + "] has been stopped."); | ||||||
|         } catch (EventDoesNotExistException e) { |         } catch (EventDoesNotExistException e) { | ||||||
|           System.out.println(e.getMessage()); |           System.out.println(e.getMessage()); | ||||||
|         } |         } | ||||||
|       } else if (option == 3) { |       } else if (option == 3) { | ||||||
|         System.out.print("Event ID: "); |         System.out.print("Event ID: "); | ||||||
|         int eventID = s.nextInt(); |         int eventId = s.nextInt(); | ||||||
|         try { |         try { | ||||||
|           eventManager.getStatus(eventID); |           eventManager.getStatus(eventId); | ||||||
|         } catch (EventDoesNotExistException e) { |         } catch (EventDoesNotExistException e) { | ||||||
|           System.out.println(e.getMessage()); |           System.out.println(e.getMessage()); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -23,15 +23,15 @@ package com.iluwatar.event.asynchronous; | |||||||
|  */ |  */ | ||||||
| public class Event implements IEvent, Runnable { | public class Event implements IEvent, Runnable { | ||||||
|  |  | ||||||
|   private int eventID; |   private int eventId; | ||||||
|   private int eventTime; |   private int eventTime; | ||||||
|   private Thread thread; |   private Thread thread; | ||||||
|   private long counter = 0; |   private long counter = 0; | ||||||
|   private boolean isComplete = false; |   private boolean isComplete = false; | ||||||
|   private ThreadCompleteListener eventListener; |   private ThreadCompleteListener eventListener; | ||||||
|  |  | ||||||
|   public Event(int eventID, int eventTime) { |   public Event(int eventId, int eventTime) { | ||||||
|     this.eventID = eventID; |     this.eventId = eventId; | ||||||
|     this.eventTime = eventTime; |     this.eventTime = eventTime; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -49,9 +49,9 @@ public class Event implements IEvent, Runnable { | |||||||
|   @Override |   @Override | ||||||
|   public void status() { |   public void status() { | ||||||
|     if (!isComplete) { |     if (!isComplete) { | ||||||
|       System.out.println("[" + eventID + "] I am at not done. [" + counter + "%]"); |       System.out.println("[" + eventId + "] I am at not done. [" + counter + "%]"); | ||||||
|     } else { |     } else { | ||||||
|       System.out.println("[" + eventID + "] I am done."); |       System.out.println("[" + eventId + "] I am done."); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -81,7 +81,7 @@ public class Event implements IEvent, Runnable { | |||||||
|  |  | ||||||
|   private final void notifyListener() { |   private final void notifyListener() { | ||||||
|     if (eventListener != null) { |     if (eventListener != null) { | ||||||
|       eventListener.notifyOfThreadComplete(eventID); |       eventListener.notifyOfThreadComplete(eventId); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,34 +32,53 @@ import java.util.concurrent.ConcurrentHashMap; | |||||||
|  */ |  */ | ||||||
| public class EventManager implements ThreadCompleteListener { | public class EventManager implements ThreadCompleteListener { | ||||||
|  |  | ||||||
|   private int minID = 1; |   private int minId = 1; | ||||||
|   private int maxID = Integer.MAX_VALUE - 1; // Be cautious of overflows. |   private int maxId = Integer.MAX_VALUE - 1; // Be cautious of overflows. | ||||||
|   private int maxRunningEvents = 1000; // no particular reason. Just don't wanna have too many running events. :) |   private int maxRunningEvents = 1000; // no particular reason. Just don't wanna have too many running events. :) | ||||||
|   private int maxEventTime = 1800; // in seconds / 30 minutes. |   private int maxEventTime = 1800; // in seconds / 30 minutes. | ||||||
|   private int currentlyRunningSyncEvent = -1; |   private int currentlyRunningSyncEvent = -1; | ||||||
|   private Random rand; |   private Random rand; | ||||||
|   private Map<Integer, Event> eventPool; |   private Map<Integer, Event> eventPool; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * EventManager constructor. | ||||||
|  |    * | ||||||
|  |    */ | ||||||
|   public EventManager() { |   public EventManager() { | ||||||
|     rand = new Random(1); |     rand = new Random(1); | ||||||
|     eventPool = new ConcurrentHashMap<Integer, Event>(maxRunningEvents); |     eventPool = new ConcurrentHashMap<Integer, Event>(maxRunningEvents); | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Create a Synchronous event. |   /** | ||||||
|  |    * Create a Synchronous event. | ||||||
|  |    *  | ||||||
|  |    * @param eventTime Time an event should run for. | ||||||
|  |    * @return eventId | ||||||
|  |    * @throws MaxNumOfEventsAllowedException When too many events are running at a time. | ||||||
|  |    * @throws InvalidOperationException No new synchronous events can be created when one is already running. | ||||||
|  |    * @throws LongRunningEventException Long running events are not allowed in the app. | ||||||
|  |    */ | ||||||
|   public int createSyncEvent(int eventTime) |   public int createSyncEvent(int eventTime) | ||||||
|       throws MaxNumOfEventsAllowedException, InvalidOperationException, LongRunningEventException { |       throws MaxNumOfEventsAllowedException, InvalidOperationException, LongRunningEventException { | ||||||
|     int eventID = createEvent(eventTime); |     int eventId = createEvent(eventTime); | ||||||
|     if (currentlyRunningSyncEvent != -1) { |     if (currentlyRunningSyncEvent != -1) { | ||||||
|       throw new InvalidOperationException( |       throw new InvalidOperationException( | ||||||
|           "Event [" + currentlyRunningSyncEvent + "] is still running. Please wait until it finishes and try again."); |           "Event [" + currentlyRunningSyncEvent + "] is still running. Please wait until it finishes and try again."); | ||||||
|     } |     } | ||||||
|     currentlyRunningSyncEvent = eventID; |     currentlyRunningSyncEvent = eventId; | ||||||
|  |  | ||||||
|     return eventID; |     return eventId; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Create an Asynchronous event. |   /** | ||||||
|  |    * Create an Asynchronous event. | ||||||
|  |    *  | ||||||
|  |    * @param eventTime Time an event should run for. | ||||||
|  |    * @return eventId | ||||||
|  |    * @throws MaxNumOfEventsAllowedException When too many events are running at a time. | ||||||
|  |    * @throws LongRunningEventException Long running events are not allowed in the app. | ||||||
|  |    */ | ||||||
|   public int createAsyncEvent(int eventTime) throws MaxNumOfEventsAllowedException, LongRunningEventException { |   public int createAsyncEvent(int eventTime) throws MaxNumOfEventsAllowedException, LongRunningEventException { | ||||||
|     return createEvent(eventTime); |     return createEvent(eventTime); | ||||||
|   } |   } | ||||||
| @@ -74,44 +93,65 @@ public class EventManager implements ThreadCompleteListener { | |||||||
|           "Maximum event time allowed is " + maxEventTime + " seconds. Please try again."); |           "Maximum event time allowed is " + maxEventTime + " seconds. Please try again."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     int newEventID = generateID(); |     int newEventId = generateId(); | ||||||
|  |  | ||||||
|     Event newEvent = new Event(newEventID, eventTime); |     Event newEvent = new Event(newEventId, eventTime); | ||||||
|     newEvent.addListener(this); |     newEvent.addListener(this); | ||||||
|     eventPool.put(newEventID, newEvent); |     eventPool.put(newEventId, newEvent); | ||||||
|  |  | ||||||
|     return newEventID; |     return newEventId; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public void startEvent(int eventID) throws EventDoesNotExistException { |   /** | ||||||
|     if (!eventPool.containsKey(eventID)) { |    * Starts event. | ||||||
|       throw new EventDoesNotExistException(eventID + " does not exist."); |    *  | ||||||
|  |    * @param eventId The event that needs to be started. | ||||||
|  |    * @throws EventDoesNotExistException If event does not exist in our eventPool. | ||||||
|  |    */ | ||||||
|  |   public void startEvent(int eventId) throws EventDoesNotExistException { | ||||||
|  |     if (!eventPool.containsKey(eventId)) { | ||||||
|  |       throw new EventDoesNotExistException(eventId + " does not exist."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     eventPool.get(eventID).start(); |     eventPool.get(eventId).start(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public void stopEvent(int eventID) throws EventDoesNotExistException { |   /** | ||||||
|     if (!eventPool.containsKey(eventID)) { |    * Stops event. | ||||||
|       throw new EventDoesNotExistException(eventID + " does not exist."); |    *  | ||||||
|  |    * @param eventId The event that needs to be stopped. | ||||||
|  |    * @throws EventDoesNotExistException If event does not exist in our eventPool. | ||||||
|  |    */ | ||||||
|  |   public void stopEvent(int eventId) throws EventDoesNotExistException { | ||||||
|  |     if (!eventPool.containsKey(eventId)) { | ||||||
|  |       throw new EventDoesNotExistException(eventId + " does not exist."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (eventID == currentlyRunningSyncEvent) { |     if (eventId == currentlyRunningSyncEvent) { | ||||||
|       currentlyRunningSyncEvent = -1; |       currentlyRunningSyncEvent = -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     eventPool.get(eventID).stop(); |     eventPool.get(eventId).stop(); | ||||||
|     eventPool.remove(eventID); |     eventPool.remove(eventId); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public void getStatus(int eventID) throws EventDoesNotExistException { |   /** | ||||||
|     if (!eventPool.containsKey(eventID)) { |    * Get status of a running event. | ||||||
|       throw new EventDoesNotExistException(eventID + " does not exist."); |    *  | ||||||
|  |    * @param eventId The event to inquire status of. | ||||||
|  |    * @throws EventDoesNotExistException If event does not exist in our eventPool. | ||||||
|  |    */ | ||||||
|  |   public void getStatus(int eventId) throws EventDoesNotExistException { | ||||||
|  |     if (!eventPool.containsKey(eventId)) { | ||||||
|  |       throw new EventDoesNotExistException(eventId + " does not exist."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     eventPool.get(eventID).status(); |     eventPool.get(eventId).status(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Gets status of all running events. | ||||||
|  |    */ | ||||||
|   @SuppressWarnings("rawtypes") |   @SuppressWarnings("rawtypes") | ||||||
|   public void getStatusOfAllEvents() { |   public void getStatusOfAllEvents() { | ||||||
|     Iterator it = eventPool.entrySet().iterator(); |     Iterator it = eventPool.entrySet().iterator(); | ||||||
| @@ -125,12 +165,12 @@ public class EventManager implements ThreadCompleteListener { | |||||||
|    * Returns a pseudo-random number between min and max, inclusive. The difference between min and max can be at most |    * Returns a pseudo-random number between min and max, inclusive. The difference between min and max can be at most | ||||||
|    * <code>Integer.MAX_VALUE - 1</code>. |    * <code>Integer.MAX_VALUE - 1</code>. | ||||||
|    */ |    */ | ||||||
|   private int generateID() { |   private int generateId() { | ||||||
|     // nextInt is normally exclusive of the top value, |     // nextInt is normally exclusive of the top value, | ||||||
|     // so add 1 to make it inclusive |     // so add 1 to make it inclusive | ||||||
|     int randomNum = rand.nextInt((maxID - minID) + 1) + minID; |     int randomNum = rand.nextInt((maxId - minId) + 1) + minId; | ||||||
|     while (eventPool.containsKey(randomNum)) { |     while (eventPool.containsKey(randomNum)) { | ||||||
|       randomNum = rand.nextInt((maxID - minID) + 1) + minID; |       randomNum = rand.nextInt((maxId - minId) + 1) + minId; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return randomNum; |     return randomNum; | ||||||
| @@ -140,9 +180,9 @@ public class EventManager implements ThreadCompleteListener { | |||||||
|    * Callback from an {@link Event} (once it is complete). The Event is then removed from the pool. |    * Callback from an {@link Event} (once it is complete). The Event is then removed from the pool. | ||||||
|    */ |    */ | ||||||
|   @Override |   @Override | ||||||
|   public void notifyOfThreadComplete(int eventID) { |   public void notifyOfThreadComplete(int eventId) { | ||||||
|     eventPool.get(eventID).status(); |     eventPool.get(eventId).status(); | ||||||
|     eventPool.remove(eventID); |     eventPool.remove(eventId); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -17,5 +17,5 @@ | |||||||
| package com.iluwatar.event.asynchronous; | package com.iluwatar.event.asynchronous; | ||||||
|  |  | ||||||
| public interface ThreadCompleteListener { | public interface ThreadCompleteListener { | ||||||
|   void notifyOfThreadComplete(final int eventID); |   void notifyOfThreadComplete(final int eventId); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,9 +36,9 @@ public class EventAsynchronousTest { | |||||||
|   public void testAsynchronousEvent() { |   public void testAsynchronousEvent() { | ||||||
|     EventManager eventManager = new EventManager(); |     EventManager eventManager = new EventManager(); | ||||||
|     try { |     try { | ||||||
|       int aEventID = eventManager.createAsyncEvent(60); |       int aEventId = eventManager.createAsyncEvent(60); | ||||||
|       eventManager.startEvent(aEventID); |       eventManager.startEvent(aEventId); | ||||||
|       eventManager.stopEvent(aEventID); |       eventManager.stopEvent(aEventId); | ||||||
|     } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { |     } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException e) { | ||||||
|       System.out.println(e.getMessage()); |       System.out.println(e.getMessage()); | ||||||
|     } |     } | ||||||
| @@ -48,9 +48,9 @@ public class EventAsynchronousTest { | |||||||
|   public void testSynchronousEvent() { |   public void testSynchronousEvent() { | ||||||
|     EventManager eventManager = new EventManager(); |     EventManager eventManager = new EventManager(); | ||||||
|     try { |     try { | ||||||
|       int sEventID = eventManager.createSyncEvent(60); |       int sEventId = eventManager.createSyncEvent(60); | ||||||
|       eventManager.startEvent(sEventID); |       eventManager.startEvent(sEventId); | ||||||
|       eventManager.stopEvent(sEventID); |       eventManager.stopEvent(sEventId); | ||||||
|     } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException |     } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException | ||||||
|         | InvalidOperationException e) { |         | InvalidOperationException e) { | ||||||
|       System.out.println(e.getMessage()); |       System.out.println(e.getMessage()); | ||||||
| @@ -61,10 +61,10 @@ public class EventAsynchronousTest { | |||||||
|   public void testUnsuccessfulSynchronousEvent() { |   public void testUnsuccessfulSynchronousEvent() { | ||||||
|     EventManager eventManager = new EventManager(); |     EventManager eventManager = new EventManager(); | ||||||
|     try { |     try { | ||||||
|       int sEventID = eventManager.createSyncEvent(60); |       int sEventId = eventManager.createSyncEvent(60); | ||||||
|       eventManager.startEvent(sEventID); |       eventManager.startEvent(sEventId); | ||||||
|       sEventID = eventManager.createSyncEvent(60); |       sEventId = eventManager.createSyncEvent(60); | ||||||
|       eventManager.startEvent(sEventID); |       eventManager.startEvent(sEventId); | ||||||
|     } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException |     } catch (MaxNumOfEventsAllowedException | LongRunningEventException | EventDoesNotExistException | ||||||
|         | InvalidOperationException e) { |         | InvalidOperationException e) { | ||||||
|       System.out.println(e.getMessage()); |       System.out.println(e.getMessage()); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user