1 package org.apache.slide.projector.processor.process; 2 3 import java.io.IOException ; 4 import java.util.ArrayList ; 5 import java.util.HashMap ; 6 import java.util.Iterator ; 7 import java.util.List ; 8 import java.util.Map ; 9 import java.util.logging.Level ; 10 import java.util.logging.Logger ; 11 12 import org.apache.slide.projector.ConfigurableProcessor; 13 import org.apache.slide.projector.ConfigurationException; 14 import org.apache.slide.projector.Context; 15 import org.apache.slide.projector.EnvironmentConsumer; 16 import org.apache.slide.projector.EnvironmentProvider; 17 import org.apache.slide.projector.ProcessException; 18 import org.apache.slide.projector.Processor; 19 import org.apache.slide.projector.Result; 20 import org.apache.slide.projector.Store; 21 import org.apache.slide.projector.URI; 22 import org.apache.slide.projector.descriptor.ContextException; 23 import org.apache.slide.projector.descriptor.ParameterDescriptor; 24 import org.apache.slide.projector.descriptor.ProvidedEnvironmentDescriptor; 25 import org.apache.slide.projector.descriptor.RequiredEnvironmentDescriptor; 26 import org.apache.slide.projector.descriptor.ResultDescriptor; 27 import org.apache.slide.projector.descriptor.ResultEntryDescriptor; 28 import org.apache.slide.projector.descriptor.StateDescriptor; 29 import org.apache.slide.projector.descriptor.StringValueDescriptor; 30 import org.apache.slide.projector.descriptor.ValidationException; 31 import org.apache.slide.projector.descriptor.ValueDescriptor; 32 import org.apache.slide.projector.descriptor.ValueFactoryManager; 33 import org.apache.slide.projector.engine.ProcessorManager; 34 import org.apache.slide.projector.i18n.DefaultMessage; 35 import org.apache.slide.projector.i18n.ErrorMessage; 36 import org.apache.slide.projector.i18n.ParameterMessage; 37 import org.apache.slide.projector.store.AbstractStore; 38 import org.apache.slide.projector.store.Cache; 39 import org.apache.slide.projector.util.StoreHelper; 40 import org.apache.slide.projector.value.DocumentValue; 41 import org.apache.slide.projector.value.StreamableValue; 42 import org.apache.slide.projector.value.StringValue; 43 import org.apache.slide.projector.value.Value; 44 import org.jdom.Document; 45 import org.jdom.Element; 46 import org.jdom.xpath.XPath; 47 48 import de.zeigermann.xml.simpleImporter.ConversionHelpers; 49 50 public class Process implements ConfigurableProcessor, EnvironmentConsumer, EnvironmentProvider { 51 private static Logger logger = Logger.getLogger(Process .class.getName()); 52 53 public final static String STEP = "step"; 54 private final static String OK = "ok"; 55 56 protected Map steps; 57 protected String firstStep; 58 59 protected RequiredEnvironmentDescriptor[] requiredEnvironmentDescriptors; 60 protected ProvidedEnvironmentDescriptor[] providedEnvironmentDescriptors; 61 protected ParameterDescriptor[] parameterDescriptors; 62 protected ResultDescriptor resultDescriptor = ResultDescriptor.OK; 63 64 public void configure(StreamableValue config) throws ConfigurationException { 65 steps = new HashMap (); 66 try { 67 DocumentValue documentResource = new DocumentValue(config); 68 Document document = documentResource.getDocument(); 69 Element rootElement = document.getRootElement(); 70 firstStep = rootElement.getAttributeValue("first-step"); 71 List inputParamters = XPath.newInstance("/process/description/input/parameter").selectNodes(rootElement); 72 List parameterDescriptors = new ArrayList (); 73 for ( Iterator i = inputParamters.iterator(); i.hasNext(); ) { 74 Element inputParameter = (Element)i.next(); 75 String name = inputParameter.getAttributeValue("name"); 76 String description = inputParameter.getAttributeValue("description"); 77 ParameterDescriptor parameterDescriptor; 78 if ( description != null ) { 79 parameterDescriptor = new ParameterDescriptor(name, new ParameterMessage(description), null); 80 } else { 81 parameterDescriptor = new ParameterDescriptor(name, new ParameterMessage(ParameterMessage.NO_MESSAGE_AVAILABLE, new String [] {name}), null); 82 } 83 parameterDescriptors.add(parameterDescriptor); 84 Element valueDescriptorElement = (Element)inputParameter.getChildren().iterator().next(); 85 ValueDescriptor valueDescriptor = ValueFactoryManager.getInstance().loadValueDescriptor(valueDescriptorElement); 86 parameterDescriptor.setValueDescriptor(valueDescriptor); 87 } 88 this.parameterDescriptors = (ParameterDescriptor [])parameterDescriptors.toArray(new ParameterDescriptor[parameterDescriptors.size()]); 89 List outputResults = XPath.newInstance("/process/description/output/result").selectNodes(rootElement); 90 List resultEntryDescriptors = new ArrayList (); 91 for ( Iterator i = outputResults.iterator(); i.hasNext(); ) { 92 Element outputResult = (Element)i.next(); 93 String name = outputResult.getAttributeValue("name"); 94 String description = outputResult.getAttributeValue("description"); 95 String contentType = outputResult.getAttributeValue("content-type"); 96 boolean presentable = ConversionHelpers.getBoolean(outputResult.getAttributeValue("presentable"), false); 97 resultEntryDescriptors.add(new ResultEntryDescriptor(name, new DefaultMessage(description), contentType, presentable)); 98 } 99 List stateElements = XPath.newInstance("/process/description/output/state").selectNodes(rootElement); 100 List states = new ArrayList (); 101 for ( Iterator i = stateElements.iterator(); i.hasNext(); ) { 102 Element stateElement = (Element)i.next(); 103 String description = stateElement.getAttributeValue("description"); 104 states.add(new StateDescriptor(stateElement.getTextTrim(), new DefaultMessage(description))); 105 } 106 resultDescriptor = new ResultDescriptor((StateDescriptor [])states.toArray(new StateDescriptor[states.size()]), (ResultEntryDescriptor[])resultEntryDescriptors.toArray(new ResultEntryDescriptor[resultEntryDescriptors.size()])); 107 List providedEnvironmentElements = XPath.newInstance("/process/description/output/environment").selectNodes(rootElement); 108 List providedEnvironment = new ArrayList (); 109 for ( Iterator i = providedEnvironmentElements.iterator(); i.hasNext(); ) { 110 Element environmentElement = (Element)i.next(); 111 String key = environmentElement.getAttributeValue("key"); 112 String storeName = environmentElement.getAttributeValue("store"); 113 String description = environmentElement.getAttributeValue("description"); 114 String contentType = environmentElement.getAttributeValue("content-type"); 115 boolean presentable = ConversionHelpers.getBoolean(environmentElement.getAttributeValue("presentable"), false); 116 int store = StoreHelper.getStoreByName(storeName); 117 ProvidedEnvironmentDescriptor environmentDescriptor = new ProvidedEnvironmentDescriptor(key, new DefaultMessage(description), contentType, presentable); 118 environmentDescriptor.setStore(store); 119 providedEnvironment.add(environmentDescriptor); 120 } 121 providedEnvironmentDescriptors = (ProvidedEnvironmentDescriptor [])providedEnvironment.toArray(new ProvidedEnvironmentDescriptor[providedEnvironment.size()]); 122 List requiredEnvironmentElements = XPath.newInstance("/process/description/input/environment").selectNodes(rootElement); 123 List requiredEnvironment = new ArrayList (); 124 for ( Iterator i = requiredEnvironmentElements.iterator(); i.hasNext(); ) { 125 Element requiredEnvironmentElement = (Element)i.next(); 126 String name = requiredEnvironmentElement.getAttributeValue("name"); 127 String storeName = requiredEnvironmentElement.getAttributeValue("store"); 128 int store = StoreHelper.getStoreByName(storeName); 129 String description = requiredEnvironmentElement.getAttributeValue("description"); 130 RequiredEnvironmentDescriptor environmentDescriptor; 131 if ( description != null ) { 132 environmentDescriptor = new RequiredEnvironmentDescriptor(name, store, new ParameterMessage(description), null); 133 } else { 134 environmentDescriptor = new RequiredEnvironmentDescriptor(name, store, new ParameterMessage(ParameterMessage.NO_MESSAGE_AVAILABLE, new String [] {name}), null); 135 } 136 requiredEnvironment.add(environmentDescriptor); 137 Element valueDescriptorElement = (Element)requiredEnvironmentElement.getChildren().iterator().next(); 138 ValueDescriptor valueDescriptor = ValueFactoryManager.getInstance().loadValueDescriptor(valueDescriptorElement); 139 environmentDescriptor.setValueDescriptor(valueDescriptor); 140 } 141 requiredEnvironmentDescriptors = (RequiredEnvironmentDescriptor [])requiredEnvironment.toArray(new RequiredEnvironmentDescriptor[requiredEnvironment.size()]); 142 List stepElements = XPath.newInstance("/process/step").selectNodes(rootElement); 143 for ( Iterator i = stepElements.iterator(); i.hasNext(); ) { 144 Element stepElement = (Element)i.next(); 145 Step step = new Step(); 146 step.configure(stepElement); 147 steps.put(step.getName(), step); 148 } 149 } catch (Exception exception) { 150 logger.log(Level.SEVERE, "Error while parsing process configuration", exception); 151 throw new ConfigurationException(new ErrorMessage("process/configurationException"), exception); 152 } 153 } 154 155 public Result process(Map parameter, Context context) throws Exception { 156 URI processorUri = ProcessorManager.getInstance().getProcessorDescriptor(this).getUri(); 157 context.setProcess(processorUri); String nextStep = getStep(firstStep, context); Store stepStore = new Cache(); Result result = new Result(OK); Result stepResult = null; Step step; Store enclosingStepStore = context.getStore(Store.STEP); 164 Map enclosingParameters = ((Cache)context.getStore(Store.INPUT)).getMap(); 165 context.setStepStore(stepStore); 166 context.setInputParameters(parameter); 167 do { 168 logger.log(Level.FINE, "Processing "+processorUri+", step=" + nextStep); 169 context.setStep(nextStep); step = (Step)steps.get(nextStep); 171 if (step == null) throw new ProcessException(new ErrorMessage("stepNotFound", new String []{nextStep})); 172 Processor processor = ProcessorManager.getInstance().getProcessor(step.getProcessorURI()); 173 try { 174 Map processorParameters = loadParameters(step, processor, context); 175 if ( processor instanceof EnvironmentConsumer ) { 176 checkRequirements((EnvironmentConsumer)processor, context); 177 } 178 checkRoutings(step, processor); 179 try { 180 stepResult = ProcessorManager.process(processor, processorParameters, context); 181 try { 182 saveResults(step, stepResult, stepStore, result, getResultDescriptor().getResultEntryDescriptors(), context); 183 } catch ( ProcessException e ) { 184 throw new ProcessException(new ErrorMessage("saveFailed", new Object [] { step.getProcessorURI(), nextStep }), e ); 185 } 186 nextStep = routeState(step, stepResult.getState()); 187 } catch (Exception e) { 188 nextStep = routeException(step, e); 189 } 190 } catch ( ValidationException exception ) { 191 throw new ValidationException(new ErrorMessage("validationFailed", new Object [] { step.getProcessorURI(), nextStep }), exception); 192 } 193 } while (nextStep != null); 194 result.setState(getState(step, stepResult.getState())); 195 context.setStepStore(enclosingStepStore); 196 context.setInputParameters(enclosingParameters); 197 return result; 198 } 199 200 public ParameterDescriptor[] getParameterDescriptors() { 201 return parameterDescriptors; 202 } 203 204 public ResultDescriptor getResultDescriptor() { 205 return resultDescriptor; 206 } 207 208 public RequiredEnvironmentDescriptor[] getRequiredEnvironmentDescriptors() { 209 return requiredEnvironmentDescriptors; 210 } 211 212 public ProvidedEnvironmentDescriptor[] getProvidedEnvironmentDescriptors() { 213 return providedEnvironmentDescriptors; 214 } 215 216 static String getStep(String firstStep, Context context) { 217 Store sessionStore = context.getStore(Store.SESSION); 218 if ( sessionStore != null ) { 219 Value stepParameter = (Value)StoreHelper.get(sessionStore, context.getProcess().toString(), STEP); 220 if (stepParameter != null && stepParameter instanceof StringValue ) { 221 return stepParameter.toString(); 222 } 223 } 224 return firstStep; 225 } 226 227 static void checkRoutings(Step step, Processor processor) throws ValidationException { 228 ResultDescriptor resultDescriptor = processor.getResultDescriptor(); 229 StateDescriptor[] states = resultDescriptor.getStateDescriptors(); 230 for ( int i = 0; i < states.length; i++ ) { 231 String state = states[i].getState(); 232 List routings = step.getRoutingConfigurations(); 233 boolean routingFound = false; 234 for ( Iterator j = routings.iterator(); j.hasNext() ; ) { 235 if ( ((RoutingConfiguration)j.next()).getState().equals(state) ) { 236 routingFound = true; 237 break; 238 } 239 } 240 if ( !routingFound ) { 241 throw new ValidationException(new ErrorMessage("stateNotRouted", new String [] { step.getName(), state })); 242 } 243 } 244 } 245 246 public static void checkRequirements(EnvironmentConsumer processor, Context context) throws ValidationException, IOException { 247 RequiredEnvironmentDescriptor[] requirementDescriptor = processor.getRequiredEnvironmentDescriptors(); 248 for ( int i = 0; i < requirementDescriptor.length; i++ ) { 249 Store store = context.getStore(requirementDescriptor[i].getStore()); 250 Object value = store.get(requirementDescriptor[i].getName()); 251 if ( value == null ) { 252 if ( requirementDescriptor[i].isRequired() ) { 253 throw new ContextException(new ErrorMessage("requiredContextMissing", new Object [] { requirementDescriptor[i].getName(), Store.stores[requirementDescriptor[i].getStore()] })); 254 } else { 255 value = requirementDescriptor[i].getDefaultValue(); 256 store.put(requirementDescriptor[i].getName(), value); 257 } 258 } 259 Value castedValue = requirementDescriptor[i].getValueDescriptor().valueOf(value, context); 260 requirementDescriptor[i].getValueDescriptor().validate(castedValue, context); 261 if ( castedValue != value ) { 262 store.put(requirementDescriptor[i].getName(), castedValue); 263 } 264 } 265 } 266 267 public static String evaluateKey(String key, Context context) { 268 int start, end = 0; 269 while ( (start = key.indexOf('{') ) != -1 ) { 270 end = key.indexOf('}'); 271 if ( end == -1 ) break; 272 int delimiter = key.indexOf(':', start); 273 String storeToken = key.substring(start+1, delimiter); 274 String keyToken = key.substring(delimiter+1, end); 275 Store keyStore = context.getStore(StoreHelper.getStoreByName(storeToken)); 276 String evaluatedKey = null; 277 if ( keyStore != null ) { 278 try { 279 Object dynamicKey = keyStore.get(keyToken); 280 evaluatedKey = StringValueDescriptor.ANY.valueOf(dynamicKey, context).toString(); 281 } catch ( Exception e ) { 282 logger.log(Level.SEVERE, "Dynamic key '"+keyToken+"' could not be loaded from store '"+storeToken+"'", e); 283 } 284 } 285 if ( evaluatedKey != null ) { 286 key = key.substring(0, start)+evaluatedKey+key.substring(end+1); 287 } else { 288 key = key.substring(0, start)+key.substring(end+1); 289 } 290 } 291 return key; 292 } 293 294 public static Map loadParameters(Step step, Processor processor, Context context) throws Exception { 295 Map parameters = new HashMap (); 297 ParameterDescriptor[] parameterDescriptors = processor.getParameterDescriptors(); 298 for (int i = 0; i < parameterDescriptors.length; i++) { 299 String key = parameterDescriptors[i].getName(); 300 ParameterConfiguration parameterConfiguration = (ParameterConfiguration)step.getParameterConfigurations().get(key); 301 if ( parameterConfiguration == null ) { 302 parameters.put(key, null); 303 } else if ( parameterConfiguration != null ) { 304 parameters.put(key, parameterConfiguration.getValue()); 305 } 306 } 307 return parameters; 308 } 309 310 public static void saveResults(Step step, Result stepResult, Store stepStore, Result result, ResultEntryDescriptor[] resultEntryDescriptors, Context context) throws ProcessException { 311 for (Iterator i = step.getResultConfigurations().entrySet().iterator(); i.hasNext();) { 313 Map.Entry entry = (Map.Entry )i.next(); 314 String resultName = (String )entry.getKey(); 315 Value resultValue = (Value)stepResult.getResultEntries().get(resultName); 316 ((ResultConfiguration)entry.getValue()).storeValue(resultValue, stepStore, result, resultEntryDescriptors, context); 317 } 318 } 319 320 private static String routeState(Step step, String state) { 321 for (Iterator i = step.getRoutingConfigurations().iterator(); i.hasNext();) { 323 RoutingConfiguration routingConfiguration = (RoutingConfiguration)i.next(); 324 if (state.equals(routingConfiguration.getState())) { 325 if (routingConfiguration.getStep() != null) { 326 return routingConfiguration.getStep(); 327 } 328 } 329 } 330 return null; 331 } 332 333 private static String routeException(Step step, Exception e) throws Exception { 334 logger.log(Level.SEVERE, "Exception occured:", e); 335 for (Iterator i = step.getRoutingConfigurations().iterator(); i.hasNext();) { 336 RoutingConfiguration routingConfiguration = (RoutingConfiguration)i.next(); 337 Class exception = routingConfiguration.getException(); 338 if (exception != null && exception.isAssignableFrom(e.getClass())) { 339 return routingConfiguration.getStep(); 340 } 341 } 342 throw(e); 343 } 344 345 private String getState(Step step, String state) throws ProcessException { 346 for (Iterator i = step.getRoutingConfigurations().iterator(); i.hasNext();) { 348 RoutingConfiguration routingConfiguration = (RoutingConfiguration)i.next(); 349 if (routingConfiguration.getReturnValue() != null && state.equals(routingConfiguration.getState())) { 350 String returnState = routingConfiguration.getReturnValue(); 351 StateDescriptor[] validStates = resultDescriptor.getStateDescriptors(); 353 for (int j = 0; j < validStates.length; j++) { 354 if (validStates[j].getState().equals(returnState)) { 355 return returnState; 356 } 357 } 358 logger.log(Level.SEVERE, "State '" + returnState + "' not defined!"); 359 throw new ProcessException(new ErrorMessage("stateNotDefined", new String []{returnState})); 360 } 361 } 362 return OK; 363 } 364 365 private Result generateResult(String state, Result result) { 366 Result processResult = new Result(state); 367 ResultEntryDescriptor[] resultEntryDescriptors = getResultDescriptor().getResultEntryDescriptors(); 369 for (int i = 0; i < resultEntryDescriptors.length; i++) { 370 ResultEntryDescriptor descriptor = resultEntryDescriptors[i]; 371 Value resultValue = (Value)result.getResultEntries().get(descriptor.getName()); 372 if (resultValue != null) { 373 processResult.addResultEntry(descriptor.getName(), resultValue); 374 } 375 } 376 return processResult; 377 } 378 379 public class ProcessStore extends AbstractStore { 380 protected Map map = new HashMap (); 381 382 public void put(String key, Object value) throws IOException { 383 map.put(key, value); 384 } 385 386 public Object get(String key) throws IOException { 387 return map.get(key); 388 } 389 390 public void dispose(String key) throws IOException { 391 map.remove(key); 392 } 393 } 394 } | Popular Tags |