View Javadoc

1   package org.apache.commons.contract;
2   
3   import java.util.Map;
4   
5   import org.apache.commons.contract.constraints.Constraints;
6   import org.apache.commons.contract.constraints.ValidationException;
7   import org.apache.commons.contract.descriptor.ParameterDescriptor;
8   import org.apache.commons.contract.descriptor.RequiredEnvironmentDescriptor;
9   import org.apache.commons.contract.descriptor.ResultDescriptor;
10  import org.apache.commons.contract.descriptor.ResultEntryDescriptor;
11  import org.apache.commons.i18n.XMLMessageProvider;
12  import org.apache.commons.i18n.bundles.ErrorBundle;
13  
14  public class Executor {
15      static {
16          // FIXME - install() method has been removed
17          //XMLMessageProvider.install("contract/exceptions", Thread.currentThread().getContextClassLoader().getResourceAsStream("exceptions.xml"));
18          //XMLMessageProvider.install("contract/constraints", Thread.currentThread().getContextClassLoader().getResourceAsStream("constraints.xml"));
19      }
20      
21      public static void init() {};
22      
23      public static Result process(Processor processor, Map parameters, Context context) throws Exception {
24      	prepareValues(processor.getParameterDescriptors(), parameters, context);
25          if ( processor instanceof EnvironmentConsumer ) {
26              checkRequirements((EnvironmentConsumer)processor, context);
27          }
28      	Result result = processor.process(parameters, context);
29          validateResult(processor.getResultDescriptors(), result, context);
30          return result;
31      }
32      
33      public static void prepareValues(ParameterDescriptor[] parameterDescriptors, Map parameters, Context context) throws ContractViolationException {
34      	for ( int i = 0; i < parameterDescriptors.length; i++ ) {
35      		String parameterName = parameterDescriptors[i].getName();
36      		Object parameterValue = parameters.get(parameterName);
37      		Object preparedValue = prepareValue(parameterDescriptors[i], parameterValue, context);
38      		parameters.put(parameterName, preparedValue);
39      	}
40      }
41      
42      public static Object prepareValue(ParameterDescriptor parameterDescriptor, Object value, Context context) throws ContractViolationException {
43      	Object preparedValue;
44      	if ( value == null ) {
45              if ( parameterDescriptor.isRequired() ) {
46                  throw new ContractViolationException(new ErrorBundle("requiredParameterMissing", new String[] { parameterDescriptor.getName() }));
47              } else {
48                  preparedValue = parameterDescriptor.getDefaultValue();
49              }
50      	} else {
51              try {
52                  preparedValue = parameterDescriptor.getConstraints().cast(value, context);
53                  parameterDescriptor.getConstraints().validate(preparedValue, context);
54              } catch ( ContractViolationException exception ) {
55                  throw new ContractViolationException(new ErrorBundle("invalidParameter", new Object[] { parameterDescriptor.getName() }), exception);
56              }
57      	}
58      	return preparedValue;
59      }
60  
61      public static void checkRequirements(EnvironmentConsumer processor, Context context) throws ContractViolationException {
62          RequiredEnvironmentDescriptor[] requirementDescriptor = processor.getRequiredEnvironmentDescriptors();
63          for ( int i = 0; i < requirementDescriptor.length; i++ ) {
64              Store store = context.getStore(requirementDescriptor[i].getStore());
65              try {
66                  Object value = store.get(requirementDescriptor[i].getName(), context);
67                  if ( value == null ) {
68                      if ( requirementDescriptor[i].isRequired() ) {
69                          throw new ValidationException(new ErrorBundle("requiredContextMissing", new Object[] { requirementDescriptor[i].getName(), requirementDescriptor[i].getStore()}));
70                      } else {
71                          value = requirementDescriptor[i].getDefaultValue();
72                          store.put(requirementDescriptor[i].getName(), value, context);
73                      }
74                  }
75                  Object castedValue = requirementDescriptor[i].getConstraints().cast(value, context);
76                  requirementDescriptor[i].getConstraints().validate(castedValue, context);
77                  if ( castedValue != value ) {
78                      store.put(requirementDescriptor[i].getName(), castedValue, context);
79                  }
80              } catch ( StoreException exception ) {
81                  throw new ContractViolationException(new ErrorBundle("storeUnaccessable", new Object[] { requirementDescriptor[i].getName(), requirementDescriptor[i].getStore()}));
82              }
83          }
84      }
85      
86  
87      public static void validateResult(ResultDescriptor[] resultDescriptors, Result result, Context context) throws ContractViolationException {
88          ResultEntryDescriptor []entryDescriptors = getResultDescriptorByState(resultDescriptors, result.getState()).getResultEntryDescriptors();
89          Map resultEntries = result.getResultEntries();
90          String name = null;
91          Object value = null;
92          try {
93              for ( int i = 0; i < entryDescriptors.length; i++ ) {
94                  ResultEntryDescriptor entryDescriptor = entryDescriptors[i];
95                  name = entryDescriptor.getName();
96                  value = resultEntries.get(name);
97                  if ( value == null ) throw new ContractViolationException(new ErrorBundle("missingResultEntry", new String[] { name }));
98                  Constraints constraints = entryDescriptor.getConstraints();
99                  if ( constraints == null ) throw new ContractViolationException(new ErrorBundle("undefinedResultEntryConstraints", new String[] { name }));
100                 value = constraints.cast(value, context);
101                 entryDescriptor.getConstraints().validate(value, context);
102                 resultEntries.put(name, value);
103             } 
104         } catch ( ValidationException exception ) {
105             throw new ContractViolationException(new ErrorBundle("invalidResultEntry", new Object[] { name, value }), exception);
106         }
107     }
108 
109     public static ResultDescriptor getResultDescriptorByState(ResultDescriptor[] resultDescriptors, String state) throws ContractViolationException {
110         for ( int i = 0; i < resultDescriptors.length; i++ ) {
111             if ( resultDescriptors[i].getStateDescriptor().getState().equals(state)) {
112                 return resultDescriptors[i];
113             }
114         }
115         throw new ContractViolationException(new ErrorBundle("stateNotDefined", new Object[] { state }));
116     }
117 }