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
17
18
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 }