Package org.apache.slide.projector.processor.process

Source Code of org.apache.slide.projector.processor.process.Process$ProcessStore

package org.apache.slide.projector.processor.process;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.slide.projector.ConfigurableProcessor;
import org.apache.slide.projector.ConfigurationException;
import org.apache.slide.projector.Context;
import org.apache.slide.projector.EnvironmentConsumer;
import org.apache.slide.projector.EnvironmentProvider;
import org.apache.slide.projector.ProcessException;
import org.apache.slide.projector.Processor;
import org.apache.slide.projector.Result;
import org.apache.slide.projector.Store;
import org.apache.slide.projector.URI;
import org.apache.slide.projector.descriptor.ContextException;
import org.apache.slide.projector.descriptor.ParameterDescriptor;
import org.apache.slide.projector.descriptor.ProvidedEnvironmentDescriptor;
import org.apache.slide.projector.descriptor.RequiredEnvironmentDescriptor;
import org.apache.slide.projector.descriptor.ResultDescriptor;
import org.apache.slide.projector.descriptor.ResultEntryDescriptor;
import org.apache.slide.projector.descriptor.StateDescriptor;
import org.apache.slide.projector.descriptor.StringValueDescriptor;
import org.apache.slide.projector.descriptor.ValidationException;
import org.apache.slide.projector.descriptor.ValueDescriptor;
import org.apache.slide.projector.descriptor.ValueFactoryManager;
import org.apache.slide.projector.engine.ProcessorManager;
import org.apache.slide.projector.i18n.DefaultMessage;
import org.apache.slide.projector.i18n.ErrorMessage;
import org.apache.slide.projector.i18n.ParameterMessage;
import org.apache.slide.projector.store.AbstractStore;
import org.apache.slide.projector.store.Cache;
import org.apache.slide.projector.util.StoreHelper;
import org.apache.slide.projector.value.DocumentValue;
import org.apache.slide.projector.value.StreamableValue;
import org.apache.slide.projector.value.StringValue;
import org.apache.slide.projector.value.Value;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.xpath.XPath;

import de.zeigermann.xml.simpleImporter.ConversionHelpers;

public class Process implements ConfigurableProcessor, EnvironmentConsumer, EnvironmentProvider {
  private static Logger logger = Logger.getLogger(Process.class.getName());
 
  public final static String STEP = "step";
  private final static String OK = "ok";
 
  protected Map steps;
  protected String firstStep;
 
  protected RequiredEnvironmentDescriptor[] requiredEnvironmentDescriptors;
  protected ProvidedEnvironmentDescriptor[] providedEnvironmentDescriptors;
  protected ParameterDescriptor[] parameterDescriptors;
  protected ResultDescriptor resultDescriptor = ResultDescriptor.OK;
 
  public void configure(StreamableValue config) throws ConfigurationException {
    steps = new HashMap();
    try {
      DocumentValue documentResource = new DocumentValue(config);
      Document document = documentResource.getDocument();
      Element rootElement = document.getRootElement();
      firstStep = rootElement.getAttributeValue("first-step");
      List inputParamters = XPath.newInstance("/process/description/input/parameter").selectNodes(rootElement);
      List parameterDescriptors = new ArrayList();
      for ( Iterator i = inputParamters.iterator(); i.hasNext(); ) {
        Element inputParameter = (Element)i.next();
        String name = inputParameter.getAttributeValue("name");
        String description = inputParameter.getAttributeValue("description");
        ParameterDescriptor parameterDescriptor;
        if ( description != null ) {
          parameterDescriptor = new ParameterDescriptor(name, new ParameterMessage(description), null);
        } else {
          parameterDescriptor = new ParameterDescriptor(name, new ParameterMessage(ParameterMessage.NO_MESSAGE_AVAILABLE, new String[] {name}), null);
        }
        parameterDescriptors.add(parameterDescriptor);
        Element valueDescriptorElement = (Element)inputParameter.getChildren().iterator().next();
        ValueDescriptor valueDescriptor = ValueFactoryManager.getInstance().loadValueDescriptor(valueDescriptorElement);
        parameterDescriptor.setValueDescriptor(valueDescriptor);
      }
      this.parameterDescriptors = (ParameterDescriptor [])parameterDescriptors.toArray(new ParameterDescriptor[parameterDescriptors.size()]);
      List outputResults = XPath.newInstance("/process/description/output/result").selectNodes(rootElement);
      List resultEntryDescriptors = new ArrayList();
      for ( Iterator i = outputResults.iterator(); i.hasNext(); ) {
        Element outputResult = (Element)i.next();
        String name = outputResult.getAttributeValue("name");
        String description = outputResult.getAttributeValue("description");
        String contentType = outputResult.getAttributeValue("content-type");
        boolean presentable = ConversionHelpers.getBoolean(outputResult.getAttributeValue("presentable"), false);
        resultEntryDescriptors.add(new ResultEntryDescriptor(name, new DefaultMessage(description), contentType, presentable));
      }
      List stateElements = XPath.newInstance("/process/description/output/state").selectNodes(rootElement);
      List states = new ArrayList();
      for ( Iterator i = stateElements.iterator(); i.hasNext(); ) {
        Element stateElement = (Element)i.next();
        String description = stateElement.getAttributeValue("description");
        states.add(new StateDescriptor(stateElement.getTextTrim(), new DefaultMessage(description)));
      }
      resultDescriptor = new ResultDescriptor((StateDescriptor [])states.toArray(new StateDescriptor[states.size()]), (ResultEntryDescriptor[])resultEntryDescriptors.toArray(new ResultEntryDescriptor[resultEntryDescriptors.size()]));
      List providedEnvironmentElements = XPath.newInstance("/process/description/output/environment").selectNodes(rootElement);
      List providedEnvironment = new ArrayList();
      for ( Iterator i = providedEnvironmentElements.iterator(); i.hasNext(); ) {
        Element environmentElement = (Element)i.next();
        String key = environmentElement.getAttributeValue("key");
        String storeName = environmentElement.getAttributeValue("store");
        String description = environmentElement.getAttributeValue("description");
        String contentType = environmentElement.getAttributeValue("content-type");
        boolean presentable = ConversionHelpers.getBoolean(environmentElement.getAttributeValue("presentable"), false);
        int store = StoreHelper.getStoreByName(storeName);
        ProvidedEnvironmentDescriptor environmentDescriptor = new ProvidedEnvironmentDescriptor(key, new DefaultMessage(description), contentType, presentable);
        environmentDescriptor.setStore(store);
        providedEnvironment.add(environmentDescriptor);
      }
      providedEnvironmentDescriptors = (ProvidedEnvironmentDescriptor [])providedEnvironment.toArray(new ProvidedEnvironmentDescriptor[providedEnvironment.size()]);
      List requiredEnvironmentElements = XPath.newInstance("/process/description/input/environment").selectNodes(rootElement);
      List requiredEnvironment = new ArrayList();
      for ( Iterator i = requiredEnvironmentElements.iterator(); i.hasNext(); ) {
        Element requiredEnvironmentElement = (Element)i.next();
        String name = requiredEnvironmentElement.getAttributeValue("name");
        String storeName = requiredEnvironmentElement.getAttributeValue("store");
        int store = StoreHelper.getStoreByName(storeName);
        String description = requiredEnvironmentElement.getAttributeValue("description");
        RequiredEnvironmentDescriptor environmentDescriptor;
        if ( description != null ) {
          environmentDescriptor = new RequiredEnvironmentDescriptor(name, store, new ParameterMessage(description), null);
        } else {
          environmentDescriptor = new RequiredEnvironmentDescriptor(name, store, new ParameterMessage(ParameterMessage.NO_MESSAGE_AVAILABLE, new String[] {name}), null);
        }
        requiredEnvironment.add(environmentDescriptor);
        Element valueDescriptorElement = (Element)requiredEnvironmentElement.getChildren().iterator().next();
        ValueDescriptor valueDescriptor = ValueFactoryManager.getInstance().loadValueDescriptor(valueDescriptorElement);
        environmentDescriptor.setValueDescriptor(valueDescriptor);
      }
      requiredEnvironmentDescriptors = (RequiredEnvironmentDescriptor [])requiredEnvironment.toArray(new RequiredEnvironmentDescriptor[requiredEnvironment.size()]);
      List stepElements = XPath.newInstance("/process/step").selectNodes(rootElement);
      for ( Iterator i = stepElements.iterator(); i.hasNext(); ) {
        Element stepElement = (Element)i.next();
        Step step = new Step();
        step.configure(stepElement);
        steps.put(step.getName(), step);
      }
    } catch (Exception exception) {
      logger.log(Level.SEVERE, "Error while parsing process configuration", exception);
      throw new ConfigurationException(new ErrorMessage("process/configurationException"), exception);
    }
  }
 
  public Result process(Map parameter, Context context) throws Exception {
    URI processorUri = ProcessorManager.getInstance().getProcessorDescriptor(this).getUri();
    context.setProcess(processorUri);        // Remember current process in context
    String nextStep = getStep(firstStep, context);   // Lookup the first step of this process
    Store stepStore = new Cache();           // This store is used to allow stack-like result/parameter delivery between steps 
    Result result = new Result(OK);         // The result of this process processor
    Result stepResult = null;               // The result of the last executed step
    Step step;                    // The current step
    Store enclosingStepStore = context.getStore(Store.STEP)
    Map enclosingParameters = ((Cache)context.getStore(Store.INPUT)).getMap()
    context.setStepStore(stepStore);
    context.setInputParameters(parameter);
    do {
      logger.log(Level.FINE, "Processing "+processorUri+", step=" + nextStep);
      context.setStep(nextStep);          // Remember current step in context
      step = (Step)steps.get(nextStep);
      if (step == null) throw new ProcessException(new ErrorMessage("stepNotFound", new String[]{nextStep}));
      Processor processor = ProcessorManager.getInstance().getProcessor(step.getProcessorURI());
      try {
        Map processorParameters = loadParameters(step, processor, context);
        if ( processor instanceof EnvironmentConsumer ) {
          checkRequirements((EnvironmentConsumer)processor, context);
        }
        checkRoutings(step, processor);
        try {
          stepResult = ProcessorManager.process(processor, processorParameters, context);
          try {
            saveResults(step, stepResult, stepStore, result, getResultDescriptor().getResultEntryDescriptors(), context);
          } catch ( ProcessException e ) {
            throw new ProcessException(new ErrorMessage("saveFailed", new Object[] { step.getProcessorURI(), nextStep }), e );
          }
          nextStep = routeState(step, stepResult.getState());
        } catch (Exception e) {
          nextStep = routeException(step, e);
        }
      } catch ( ValidationException exception ) {
        throw new ValidationException(new ErrorMessage("validationFailed", new Object[] { step.getProcessorURI(), nextStep }), exception);
      }
    } while (nextStep != null);
    result.setState(getState(step, stepResult.getState()));
    context.setStepStore(enclosingStepStore);
    context.setInputParameters(enclosingParameters);
    return result;
  }
 
  public ParameterDescriptor[] getParameterDescriptors() {
    return parameterDescriptors;
  }
 
  public ResultDescriptor getResultDescriptor() {
    return resultDescriptor;
  }
 
  public RequiredEnvironmentDescriptor[] getRequiredEnvironmentDescriptors() {
    return requiredEnvironmentDescriptors;
  }
 
  public ProvidedEnvironmentDescriptor[] getProvidedEnvironmentDescriptors() {
    return providedEnvironmentDescriptors;
  }
 
  static String getStep(String firstStep, Context context) {
    Store sessionStore = context.getStore(Store.SESSION);
    if ( sessionStore != null ) {
      Value stepParameter = (Value)StoreHelper.get(sessionStore, context.getProcess().toString(), STEP);
      if (stepParameter != null && stepParameter instanceof StringValue ) {
        return stepParameter.toString();
      }
    }
    return firstStep;
  }
 
  static void checkRoutings(Step step, Processor processor) throws ValidationException {
    ResultDescriptor resultDescriptor = processor.getResultDescriptor();
    StateDescriptor[] states = resultDescriptor.getStateDescriptors();
    for ( int i = 0; i < states.length; i++ ) {
      String state = states[i].getState();
      List routings = step.getRoutingConfigurations();
      boolean routingFound = false;
      for ( Iterator j = routings.iterator(); j.hasNext() ; ) {
        if ( ((RoutingConfiguration)j.next()).getState().equals(state) ) {
          routingFound = true;
          break;
        }
      }
      if ( !routingFound ) {
        throw new ValidationException(new ErrorMessage("stateNotRouted", new String[] { step.getName(), state }));
      }
    }
  }
 
  public static void checkRequirements(EnvironmentConsumer processor, Context context) throws ValidationException, IOException {
    RequiredEnvironmentDescriptor[] requirementDescriptor = processor.getRequiredEnvironmentDescriptors();
    for ( int i = 0; i < requirementDescriptor.length; i++ ) {
      Store store = context.getStore(requirementDescriptor[i].getStore());
      Object value = store.get(requirementDescriptor[i].getName());
      if ( value == null ) {
        if ( requirementDescriptor[i].isRequired() ) {
          throw new ContextException(new ErrorMessage("requiredContextMissing", new Object[] { requirementDescriptor[i].getName(), Store.stores[requirementDescriptor[i].getStore()] }));
        } else {
          value = requirementDescriptor[i].getDefaultValue();
          store.put(requirementDescriptor[i].getName(), value);
        }
      }
      Value castedValue = requirementDescriptor[i].getValueDescriptor().valueOf(value, context);
      requirementDescriptor[i].getValueDescriptor().validate(castedValue, context);
      if ( castedValue != value ) {
        store.put(requirementDescriptor[i].getName(), castedValue);
      }
    }
  }
 
  public static String evaluateKey(String key, Context context) {
    int start, end = 0;
    while ( (start = key.indexOf('{') ) != -1 ) {
      end = key.indexOf('}');
      if ( end == -1 ) break;
      int delimiter = key.indexOf(':', start);
      String storeToken = key.substring(start+1, delimiter);
      String keyToken = key.substring(delimiter+1, end);
      Store keyStore = context.getStore(StoreHelper.getStoreByName(storeToken));
      String evaluatedKey = null;
      if ( keyStore != null ) {
        try {
          Object dynamicKey = keyStore.get(keyToken);
          evaluatedKey = StringValueDescriptor.ANY.valueOf(dynamicKey, context).toString();
        } catch ( Exception e ) {
          logger.log(Level.SEVERE, "Dynamic key '"+keyToken+"' could not be loaded from store '"+storeToken+"'", e);
        }
      }
      if ( evaluatedKey != null ) {
        key = key.substring(0, start)+evaluatedKey+key.substring(end+1);
      } else {
        key = key.substring(0, start)+key.substring(end+1);
      }
    }
    return key;
  }
 
  public static Map loadParameters(Step step, Processor processor, Context context) throws Exception {
    // Collect parameters for this processor
    Map parameters = new HashMap();
    ParameterDescriptor[] parameterDescriptors = processor.getParameterDescriptors();
    for (int i = 0; i < parameterDescriptors.length; i++) {
      String key = parameterDescriptors[i].getName();
      ParameterConfiguration parameterConfiguration = (ParameterConfiguration)step.getParameterConfigurations().get(key);
      if ( parameterConfiguration == null ) {
        parameters.put(key, null);
      } else if ( parameterConfiguration != null ) {
        parameters.put(key, parameterConfiguration.getValue());
      }
    }
    return parameters;
  }

  public static void saveResults(Step step, Result stepResult, Store stepStore, Result result, ResultEntryDescriptor[] resultEntryDescriptors, Context context) throws ProcessException {
    // save results by using result configuration
    for (Iterator i = step.getResultConfigurations().entrySet().iterator(); i.hasNext();) {
      Map.Entry entry = (Map.Entry)i.next();
      String resultName = (String)entry.getKey();
      Value resultValue = (Value)stepResult.getResultEntries().get(resultName);
      ((ResultConfiguration)entry.getValue()).storeValue(resultValue, stepStore, result, resultEntryDescriptors, context);
    }
  }
 
  private static String routeState(Step step, String state) {
    // find routing for result state
    for (Iterator i = step.getRoutingConfigurations().iterator(); i.hasNext();) {
      RoutingConfiguration routingConfiguration = (RoutingConfiguration)i.next();
      if (state.equals(routingConfiguration.getState())) {
        if (routingConfiguration.getStep() != null) {
          return routingConfiguration.getStep();
        }
      }
    }
    return null;
  }
 
  private static String routeException(Step step, Exception e) throws Exception {
    logger.log(Level.SEVERE, "Exception occured:", e);
    for (Iterator i = step.getRoutingConfigurations().iterator(); i.hasNext();) {
      RoutingConfiguration routingConfiguration = (RoutingConfiguration)i.next();
      Class exception = routingConfiguration.getException();
      if (exception != null && exception.isAssignableFrom(e.getClass())) {
        return routingConfiguration.getStep();
      }
    }
    throw(e);
  }
 
  private String getState(Step step, String state) throws ProcessException {
    // find processor return state for result state
    for (Iterator i = step.getRoutingConfigurations().iterator(); i.hasNext();) {
      RoutingConfiguration routingConfiguration = (RoutingConfiguration)i.next();
      if (routingConfiguration.getReturnValue() != null && state.equals(routingConfiguration.getState())) {
        String returnState = routingConfiguration.getReturnValue();
        // check if state is legal
        StateDescriptor[] validStates = resultDescriptor.getStateDescriptors();
        for (int j = 0; j < validStates.length; j++) {
          if (validStates[j].getState().equals(returnState)) {
            return returnState;
          }
        }
        logger.log(Level.SEVERE, "State '" + returnState + "' not defined!");
        throw new ProcessException(new ErrorMessage("stateNotDefined", new String[]{returnState}));
      }
    }
    return OK;
  }
 
  private Result generateResult(String state, Result result) {
    Result processResult = new Result(state);
    // copy defined results from context store to result
    ResultEntryDescriptor[] resultEntryDescriptors = getResultDescriptor().getResultEntryDescriptors();
    for (int i = 0; i < resultEntryDescriptors.length; i++) {
      ResultEntryDescriptor descriptor = resultEntryDescriptors[i];
      Value resultValue = (Value)result.getResultEntries().get(descriptor.getName());
      if (resultValue != null) {
        processResult.addResultEntry(descriptor.getName(), resultValue);
      }
    }
    return processResult;
  }
 
  public class ProcessStore extends AbstractStore {
    protected Map map = new HashMap();
   
    public void put(String key, Object value) throws IOException {
      map.put(key, value);
    }
   
    public Object get(String key) throws IOException {
      return map.get(key);
    }
   
    public void dispose(String key) throws IOException {
      map.remove(key);
    }
  }
}
TOP

Related Classes of org.apache.slide.projector.processor.process.Process$ProcessStore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.