001 /* 002 * Operation 003 * 004 * Copyright (c) 2000, 2001, 2002 Marco Schmidt <marcoschmidt@users.sourceforge.net> 005 * All rights reserved. 006 */ 007 008 package net.sourceforge.jiu.ops; 009 010 import java.util.Vector; 011 import net.sourceforge.jiu.ops.MissingParameterException; 012 import net.sourceforge.jiu.ops.OperationFailedException; 013 import net.sourceforge.jiu.ops.ProgressListener; 014 import net.sourceforge.jiu.ops.WrongParameterException; 015 016 /** 017 * <p> 018 * Base class for all operations. 019 * </p> 020 * <p> 021 * It supports progress notification. 022 * All classes that want to be notified by a new progress level of the operation 023 * (defined as value between 0.0f (nothing has been done so far) to 1.0f 024 * (operation finished)) must implement the {@link ProgressListener} interface. 025 * </p> 026 * <p> 027 * An abortion state is stored in each Operation object. 028 * It should be queried by a running operation from time to time 029 * (via {@link #getAbort()} - if it returns <code>true</code>, 030 * the operation should terminate and return control to the caller. 031 * The abort state can be modified using {@link #setAbort(boolean)}. 032 * </p> 033 * @author Marco Schmidt 034 */ 035 public abstract class Operation 036 { 037 /* <p> 038 * This class class contains a generic system to add parameters to an operation. 039 * Whether an item becomes a parameter is often unclear and must be decided by 040 * the operation implementor. 041 * As an example: one could create an image rotation class with a numerical parameter 042 * for the degrees of rotation. 043 * One could also define a class of its own for each 90, 180 and 270 degrees 044 * (excluding other values). 045 * </p> 046 * <p> 047 * The generic parameter system is insufficient in some situations. 048 * Example: A parameter can be defined to be of class Integer or Long, but it cannot 049 * be forced to be in a certain interval. 050 * Even if such a case could be solved by a specially-designed class, checking 051 * of parameters (and maybe their relations among each other) can be done by 052 * overriding the {@link #checkParams()} method. 053 * </p> 054 */ 055 private boolean abort; 056 private Vector progressListeners; 057 // private Vector params; 058 059 /** 060 * This constructor creates two internal empty lists for progress listeners and parameters. 061 */ 062 public Operation() 063 { 064 abort = false; 065 progressListeners = new Vector(); 066 // params = new Vector(); 067 } 068 069 /** 070 * Adds a new parameter to the internal list of parameters for this operation. 071 * 072 * @param parameter the Parameter object to be added 073 * 074 * @throws IllegalArgumentException if the oarameter is null or if a parameter of the 075 * same name has already been added to the internal list of parameter 076 */ 077 /* public void addParam(Parameter parameter) throws IllegalArgumentException 078 { 079 if (parameter == null) 080 { 081 throw new IllegalArgumentException("Parameter must be non-null."); 082 } 083 String name = parameter.getName(); 084 Parameter paramInVector = getParam(name); 085 if (paramInVector != null) 086 { 087 throw new IllegalArgumentException("Parameter of the name \"" + name + "\" already exists in internal parameter list."); 088 } 089 params.addElement(parameter); 090 }*/ 091 092 /** 093 * Adds the argument progress listener to the internal list of 094 * progress listeners. 095 * Does not check if the argument already exists in that list, so you have 096 * to check for duplicates yourself. 097 * 098 * @param progressListener the progress listener to be added 099 */ 100 public void addProgressListener(ProgressListener progressListener) 101 { 102 if (progressListener == null) 103 { 104 return; 105 } 106 if (!progressListeners.contains(progressListener)) 107 { 108 progressListeners.addElement(progressListener); 109 } 110 } 111 112 /** 113 * Adds several progress listeners to this operation object. 114 * @param progressListeners contains zero or more objects implementing ProgressListener; 115 * each will be added by calling {@link #addProgressListener} on it 116 */ 117 public void addProgressListeners(Vector progressListeners) 118 { 119 if (progressListeners != null) 120 { 121 int index = 0; 122 while (index < progressListeners.size()) 123 { 124 ProgressListener listener = (ProgressListener)progressListeners.elementAt(index++); 125 addProgressListener(listener); 126 } 127 } 128 } 129 130 /** 131 * Calls the {@link Parameter#check()} method of each {@link Parameter} 132 * object in the internal list of parameters. 133 * Will throw an exception if at least one parameter with a required value 134 * has not been initialized. 135 * 136 * @throws MissingParameterException if at least one parameter is not properly initialized 137 */ 138 /* public void checkParams() throws MissingParameterException 139 { 140 int index = 0; 141 while (index < params.size()) 142 { 143 Parameter param = (Parameter)params.elementAt(index++); 144 param.check(); 145 } 146 }*/ 147 148 /** 149 * Returns the current abort status. 150 * If <code>true</code>, a running operation should terminate what it is doing 151 * (return from {@link #process()}). 152 * @return abort status 153 * @see #setAbort 154 */ 155 public boolean getAbort() 156 { 157 return abort; 158 } 159 160 /** 161 * Returns the number of parameters currently defined for this operation. 162 * @return number of defined parameters 163 */ 164 /* public int getNumParams() 165 { 166 return params.size(); 167 }*/ 168 169 /* private Parameter getParam(String paramName) 170 { 171 if (paramName == null || paramName.length() < 1) 172 { 173 return null; 174 } 175 int index = 0; 176 while (index < params.size()) 177 { 178 Parameter param = (Parameter)params.elementAt(index++); 179 if (paramName.equals(param.getName())) 180 { 181 return param; 182 } 183 } 184 return null; 185 }*/ 186 187 /** 188 * Returns a Parameter object from the internal list of parameters. 189 * @param index zero-based index of the parameter; must be smaller than {@link #getNumParams()} 190 */ 191 /* public Parameter getParam(int index) 192 { 193 return (Parameter)params.elementAt(index); 194 }*/ 195 196 /* public Object getParamValue(int index) 197 { 198 Parameter param = getParam(index); 199 if (param == null) 200 { 201 return null; 202 } 203 else 204 { 205 return param.getValue(); 206 } 207 }*/ 208 209 /** 210 * This method does the actual work of the operation. 211 * It must be called after all parameters have been given to the operation object. 212 * @throws WrongParameterException if at least one of the input parameters was 213 * not initialized appropriately (values out of the valid interval, etc.) 214 * @throws MissingParameterException if any mandatory parameter was not given to the operation 215 * @throws OperationFailedException 216 */ 217 public void process() throws 218 MissingParameterException, 219 OperationFailedException, 220 WrongParameterException 221 { 222 } 223 224 /** 225 * Removes the argument progress listener from the internal list of 226 * progress listeners. 227 * @param progressListener the progress listener to be removed 228 */ 229 public void removeProgressListener(ProgressListener progressListener) 230 { 231 progressListeners.removeElement(progressListener); 232 } 233 234 /** 235 * Sets a new abort status. 236 * @param newAbortStatus the new status 237 * @see #getAbort 238 */ 239 public void setAbort(boolean newAbortStatus) 240 { 241 abort = newAbortStatus; 242 } 243 244 /** 245 * This method will notify all registered progress listeners 246 * about a new progress level. 247 * The argument must be from 0.0f to 1.0f where 0.0f marks the 248 * beginning and 1.0f completion. 249 * The progress value should not be smaller than any value that 250 * was previously set. 251 * @param progress new progress value, from 0.0 to 1.0 252 */ 253 public void setProgress(float progress) 254 { 255 if (progress < 0.0f || progress > 1.0f) 256 { 257 throw new IllegalArgumentException("Progress values must be from" + 258 " 0.0f to 1.0f; got " + progress); 259 } 260 int index = 0; 261 while (index < progressListeners.size()) 262 { 263 ProgressListener pl = 264 (ProgressListener)progressListeners.elementAt(index++); 265 if (pl != null) 266 { 267 pl.setProgress(progress); 268 } 269 } 270 } 271 272 /** 273 * This method will notify all registered progress listeners 274 * about a new progress level. 275 * Simply checks the arguments and calls <code>setProgress((float)zeroBasedIndex / (float)totalItems);</code>. 276 * @param zeroBasedIndex the index of the item that was just processed, zero-based 277 * @param totalItems the number of items that will be processed 278 */ 279 public void setProgress(int zeroBasedIndex, int totalItems) 280 { 281 if (zeroBasedIndex < 0 || zeroBasedIndex >= totalItems || 282 totalItems < 1) 283 { 284 throw new IllegalArgumentException("No valid arguments " + 285 " zeroBasedIndex=" + zeroBasedIndex + ", totalItems=" + 286 totalItems); 287 } 288 setProgress((float)zeroBasedIndex / (float)totalItems); 289 } 290 }