src/core/net/sf/basedb/util/extensions/ActionIterator.java

Code
Comments
Other
Rev Date Author Line
4170 07 Mar 08 nicklas 1 /**
4479 05 Sep 08 jari 2   $Id$
4170 07 Mar 08 nicklas 3
4170 07 Mar 08 nicklas 4   Copyright (C) Authors contributing to this file.
4170 07 Mar 08 nicklas 5
4170 07 Mar 08 nicklas 6   This file is part of BASE - BioArray Software Environment.
4170 07 Mar 08 nicklas 7   Available at http://base.thep.lu.se/
4170 07 Mar 08 nicklas 8
4170 07 Mar 08 nicklas 9   BASE is free software; you can redistribute it and/or
4170 07 Mar 08 nicklas 10   modify it under the terms of the GNU General Public License
4479 05 Sep 08 jari 11   as published by the Free Software Foundation; either version 3
4170 07 Mar 08 nicklas 12   of the License, or (at your option) any later version.
4170 07 Mar 08 nicklas 13
4170 07 Mar 08 nicklas 14   BASE is distributed in the hope that it will be useful,
4170 07 Mar 08 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
4170 07 Mar 08 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4170 07 Mar 08 nicklas 17   GNU General Public License for more details.
4170 07 Mar 08 nicklas 18
4170 07 Mar 08 nicklas 19   You should have received a copy of the GNU General Public License
4515 11 Sep 08 jari 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
4170 07 Mar 08 nicklas 21 */
4168 04 Mar 08 nicklas 22 package net.sf.basedb.util.extensions;
4168 04 Mar 08 nicklas 23
4168 04 Mar 08 nicklas 24 import java.util.Iterator;
4168 04 Mar 08 nicklas 25 import java.util.NoSuchElementException;
4168 04 Mar 08 nicklas 26
7275 24 Jan 17 nicklas 27 import net.sf.basedb.util.extensions.events.EventType;
4168 04 Mar 08 nicklas 28
7275 24 Jan 17 nicklas 29
4168 04 Mar 08 nicklas 30 /**
4170 07 Mar 08 nicklas 31   Iterator for iterating over all actions that <b>will be
4170 07 Mar 08 nicklas 32   created</b> by extensions after a call to {@link
4207 04 Apr 08 nicklas 33   Registry#useExtensions(ClientContext, ExtensionsFilter, String...)}.
4170 07 Mar 08 nicklas 34   That method returns an {@link ExtensionsInvoker} object which
4170 07 Mar 08 nicklas 35   in it's turn uses this iterator.
4170 07 Mar 08 nicklas 36   
4170 07 Mar 08 nicklas 37   <p>
4170 07 Mar 08 nicklas 38   Note the phrase "will be created" above. The actions 
4170 07 Mar 08 nicklas 39   are created on demand as this iterator moves on the 
4170 07 Mar 08 nicklas 40   next item. This happens in the {@link #hasNext()} method, which,
4170 07 Mar 08 nicklas 41   for each extension, calls {@link Extension#getActionFactory()}
4207 04 Apr 08 nicklas 42   and then {@link ActionFactory#getActions(InvokationContext)}.
4170 07 Mar 08 nicklas 43   
4170 07 Mar 08 nicklas 44   <p>
4170 07 Mar 08 nicklas 45   The actions returned from the extensions are piled up in an
4170 07 Mar 08 nicklas 46   internal buffer that the {@link #next()} method pick items from.
4170 07 Mar 08 nicklas 47   When the buffer is empty the iterator moves on to the actions from
4170 07 Mar 08 nicklas 48   next extension until there are no more extensions and the action
4170 07 Mar 08 nicklas 49   buffer is empty.
4170 07 Mar 08 nicklas 50
4170 07 Mar 08 nicklas 51   @author nicklas
4170 07 Mar 08 nicklas 52   @version 2.7
4198 28 Mar 08 nicklas 53   @base.modified $Date:2008-03-20 12:15:25 +0100 (Thu, 20 Mar 2008) $
4168 04 Mar 08 nicklas 54 */
4168 04 Mar 08 nicklas 55 public class ActionIterator<A extends Action>
4168 04 Mar 08 nicklas 56   implements Iterator<A>
4168 04 Mar 08 nicklas 57 {
4168 04 Mar 08 nicklas 58
4168 04 Mar 08 nicklas 59   // The current context
5486 12 Nov 10 nicklas 60   private ExtensionContext<A> currentContext;
4618 30 Oct 08 nicklas 61   private A currentAction;
4168 04 Mar 08 nicklas 62   
4168 04 Mar 08 nicklas 63   // An iterator over all usable extensions
5486 12 Nov 10 nicklas 64   private final Iterator<ExtensionContext<A>> iterator;
4168 04 Mar 08 nicklas 65   
4168 04 Mar 08 nicklas 66   // The actions created by the current extension
4168 04 Mar 08 nicklas 67   private A[] actions;
4168 04 Mar 08 nicklas 68   // The iterator's offset in the actions array
4168 04 Mar 08 nicklas 69   private int offset;
4168 04 Mar 08 nicklas 70   
4168 04 Mar 08 nicklas 71   // Boolean flags to indicate if we have a next element and if 
4168 04 Mar 08 nicklas 72   // we need to check or not. If both are 'false' we have reached the end
4168 04 Mar 08 nicklas 73   private boolean checkNext;
4168 04 Mar 08 nicklas 74   private boolean hasNext;
4168 04 Mar 08 nicklas 75   
4168 04 Mar 08 nicklas 76   
5486 12 Nov 10 nicklas 77   ActionIterator(Iterator<ExtensionContext<A>> iterator)
4168 04 Mar 08 nicklas 78   {
4168 04 Mar 08 nicklas 79     this.iterator = iterator;
4168 04 Mar 08 nicklas 80     this.checkNext = true;
4168 04 Mar 08 nicklas 81   }
4198 28 Mar 08 nicklas 82   /*
4198 28 Mar 08 nicklas 83     From the Iterator interface
4198 28 Mar 08 nicklas 84     ---------------------------
4198 28 Mar 08 nicklas 85   */
6127 14 Sep 12 nicklas 86   @Override
4168 04 Mar 08 nicklas 87   public boolean hasNext()
4168 04 Mar 08 nicklas 88   {
4168 04 Mar 08 nicklas 89     if (checkNext)
4168 04 Mar 08 nicklas 90     {
4168 04 Mar 08 nicklas 91       checkNext = false;
4168 04 Mar 08 nicklas 92       offset++;
4168 04 Mar 08 nicklas 93       if (actions != null && offset < actions.length)
4168 04 Mar 08 nicklas 94       {
4168 04 Mar 08 nicklas 95         // There are more actions in the array
4168 04 Mar 08 nicklas 96         hasNext = true;
4168 04 Mar 08 nicklas 97       }
4168 04 Mar 08 nicklas 98       else
4168 04 Mar 08 nicklas 99       {
4168 04 Mar 08 nicklas 100         // No more actions in the array, move on to the next extension
4207 04 Apr 08 nicklas 101         currentContext = null;
4168 04 Mar 08 nicklas 102         actions = null;
4168 04 Mar 08 nicklas 103         offset = 0;
4168 04 Mar 08 nicklas 104         hasNext = false;
4168 04 Mar 08 nicklas 105         
4168 04 Mar 08 nicklas 106         // Continue until we find an extension that creates at least one
4168 04 Mar 08 nicklas 107         // action, or until we run out of extensions
4168 04 Mar 08 nicklas 108         while (iterator.hasNext())
4168 04 Mar 08 nicklas 109         {
4207 04 Apr 08 nicklas 110           currentContext = iterator.next();
4207 04 Apr 08 nicklas 111           
4168 04 Mar 08 nicklas 112           // Get the actions for the extension
4207 04 Apr 08 nicklas 113           actions = currentContext.getActions();
4236 18 Apr 08 nicklas 114
4236 18 Apr 08 nicklas 115           // Validate that the actions are of the expected type
4236 18 Apr 08 nicklas 116           if (validActions(actions))
4168 04 Mar 08 nicklas 117           {
4168 04 Mar 08 nicklas 118             hasNext = true;
4236 18 Apr 08 nicklas 119             break;              
4168 04 Mar 08 nicklas 120           }
4168 04 Mar 08 nicklas 121         }
4168 04 Mar 08 nicklas 122       }
4168 04 Mar 08 nicklas 123     }
4168 04 Mar 08 nicklas 124     return hasNext;
4168 04 Mar 08 nicklas 125   }
4168 04 Mar 08 nicklas 126   
6127 14 Sep 12 nicklas 127   @Override
4168 04 Mar 08 nicklas 128   public A next()
4168 04 Mar 08 nicklas 129   {
4168 04 Mar 08 nicklas 130     if (checkNext) hasNext();
4168 04 Mar 08 nicklas 131     if (!hasNext) throw new NoSuchElementException();
4168 04 Mar 08 nicklas 132     checkNext = true;
4618 30 Oct 08 nicklas 133     currentAction = actions[offset];
4618 30 Oct 08 nicklas 134     return currentAction;
4168 04 Mar 08 nicklas 135   }
4168 04 Mar 08 nicklas 136   /**
4168 04 Mar 08 nicklas 137     Not supported.
4168 04 Mar 08 nicklas 138     @throws UnsupportedOperationException Always
4168 04 Mar 08 nicklas 139   */
6127 14 Sep 12 nicklas 140   @Override
4168 04 Mar 08 nicklas 141   public void remove()
4168 04 Mar 08 nicklas 142   {
4168 04 Mar 08 nicklas 143     throw new UnsupportedOperationException();
4168 04 Mar 08 nicklas 144   }
4198 28 Mar 08 nicklas 145   // ------------------------------------
4168 04 Mar 08 nicklas 146   
4168 04 Mar 08 nicklas 147   /**
4208 07 Apr 08 nicklas 148     Get the extension point that the current action
4208 07 Apr 08 nicklas 149     belongs to.
4208 07 Apr 08 nicklas 150   */
4208 07 Apr 08 nicklas 151   public ExtensionPoint<? super A> getExtensionPoint()
4208 07 Apr 08 nicklas 152   {
4208 07 Apr 08 nicklas 153     return currentContext.getExtensionPoint();
4208 07 Apr 08 nicklas 154   }
4208 07 Apr 08 nicklas 155   
4208 07 Apr 08 nicklas 156   /**
4168 04 Mar 08 nicklas 157     Get the extension that created the current action.
4168 04 Mar 08 nicklas 158   */
4170 07 Mar 08 nicklas 159   public Extension<? extends A> getExtension()
4168 04 Mar 08 nicklas 160   {
4207 04 Apr 08 nicklas 161     return currentContext.getExtension();
4168 04 Mar 08 nicklas 162   }
4168 04 Mar 08 nicklas 163   
4168 04 Mar 08 nicklas 164   /**
4168 04 Mar 08 nicklas 165     Gets the renderer for the current action.
4618 30 Oct 08 nicklas 166     @since 2.9
4168 04 Mar 08 nicklas 167   */
4618 30 Oct 08 nicklas 168   public Renderer<? super A> getRenderer()
4168 04 Mar 08 nicklas 169   {
4207 04 Apr 08 nicklas 170     return currentContext.getRenderer();
4168 04 Mar 08 nicklas 171   }
4236 18 Apr 08 nicklas 172
4236 18 Apr 08 nicklas 173   /**
7275 24 Jan 17 nicklas 174     Send the event to event handlers registered in the registry.
7461 14 Mar 18 nicklas 175     @see Registry#handleEvent(EventType, ExtensionPoint, Extension)
7275 24 Jan 17 nicklas 176     @since 3.10
7275 24 Jan 17 nicklas 177   */
7275 24 Jan 17 nicklas 178   public void handleEvent(EventType event)
7275 24 Jan 17 nicklas 179   {
7275 24 Jan 17 nicklas 180     currentContext.getRegistry().handleEvent(event, currentContext.getExtensionPoint(), currentContext.getExtension());
7275 24 Jan 17 nicklas 181   }
7275 24 Jan 17 nicklas 182   
7275 24 Jan 17 nicklas 183   /**
4618 30 Oct 08 nicklas 184     Clear any error that has been registered for the current 
4618 30 Oct 08 nicklas 185     action.
4618 30 Oct 08 nicklas 186     @since 2.9
4618 30 Oct 08 nicklas 187     @see #setError(Throwable)
4618 30 Oct 08 nicklas 188   */
4618 30 Oct 08 nicklas 189   public void clearError()
4618 30 Oct 08 nicklas 190   {
4618 30 Oct 08 nicklas 191     currentContext.clearError();
4618 30 Oct 08 nicklas 192   }
4618 30 Oct 08 nicklas 193   
4618 30 Oct 08 nicklas 194   /**
5488 15 Nov 10 nicklas 195     Register an error for the current action. The error is handled by the
5488 15 Nov 10 nicklas 196     error handler for the extension point.
4618 30 Oct 08 nicklas 197     @param t The error to register
4618 30 Oct 08 nicklas 198     @since 2.9
4618 30 Oct 08 nicklas 199   */
4618 30 Oct 08 nicklas 200   public void setError(Throwable t)
4618 30 Oct 08 nicklas 201   {
5486 12 Nov 10 nicklas 202     currentContext.handleError(currentAction, null, t);
4618 30 Oct 08 nicklas 203   }
4618 30 Oct 08 nicklas 204   
4618 30 Oct 08 nicklas 205   /**
5486 12 Nov 10 nicklas 206     Register an error with a message for the current action. The error 
5488 15 Nov 10 nicklas 207     is handled by the error handler for the extension point.
5486 12 Nov 10 nicklas 208     @param t The error to register
5486 12 Nov 10 nicklas 209     @param message An optional message
5486 12 Nov 10 nicklas 210     @since 2.17
5486 12 Nov 10 nicklas 211    */
5486 12 Nov 10 nicklas 212   public void setError(String message, Throwable t)
5486 12 Nov 10 nicklas 213   {
5486 12 Nov 10 nicklas 214     currentContext.handleError(currentAction, message, t);
5486 12 Nov 10 nicklas 215   }
5486 12 Nov 10 nicklas 216   
5486 12 Nov 10 nicklas 217   /**
4236 18 Apr 08 nicklas 218     Check that the actions array is a not-null, non-empty array
4236 18 Apr 08 nicklas 219     and contains actions of a type that is compatible with the
4236 18 Apr 08 nicklas 220     {@link ExtensionPoint#getActionClass()} class.
4236 18 Apr 08 nicklas 221     <p>
4236 18 Apr 08 nicklas 222     NOTE! If the array contains at least one invalid action, all
4236 18 Apr 08 nicklas 223     actions, including the valid ones, will be ignored. No exception
4236 18 Apr 08 nicklas 224     will be thrown. An error-level log message is written to the log
4236 18 Apr 08 nicklas 225     file.
4236 18 Apr 08 nicklas 226     
4236 18 Apr 08 nicklas 227     @param actions The actions to check
4236 18 Apr 08 nicklas 228     @return TRUE if the actions are valid, FALSE otherwise
4236 18 Apr 08 nicklas 229   */
4236 18 Apr 08 nicklas 230   private boolean validActions(A[] actions)
4236 18 Apr 08 nicklas 231   {
4236 18 Apr 08 nicklas 232     if (actions == null || actions.length == 0) return false;
4236 18 Apr 08 nicklas 233
4236 18 Apr 08 nicklas 234     Class<?> actionClass = getExtensionPoint().getActionClass();
4236 18 Apr 08 nicklas 235     for (int i = 0; i < actions.length; ++i)
4236 18 Apr 08 nicklas 236     {
4236 18 Apr 08 nicklas 237       if (!actionClass.isInstance(actions[i]))
4236 18 Apr 08 nicklas 238       {
6875 20 Apr 15 nicklas 239         Extension<?> ext = getExtension();
4236 18 Apr 08 nicklas 240         ClassCastException cc = new ClassCastException(actions[i] + " -> " + actionClass.getName());
5486 12 Nov 10 nicklas 241         currentContext.handleError(actions[i], "Action '" + actions[i] + "' created by extension '" + 
5486 12 Nov 10 nicklas 242             ext.getId() + "' is not of the expected class '" + actionClass.getName(), cc);
4236 18 Apr 08 nicklas 243         return false;
4236 18 Apr 08 nicklas 244       }
4236 18 Apr 08 nicklas 245     }
4236 18 Apr 08 nicklas 246     return true;
4236 18 Apr 08 nicklas 247   }
4236 18 Apr 08 nicklas 248
4168 04 Mar 08 nicklas 249 }