001 package org.apache.commons.contract; 002 003 import java.util.Map; 004 005 import org.apache.commons.contract.constraints.Constraints; 006 import org.apache.commons.contract.constraints.ValidationException; 007 import org.apache.commons.contract.descriptor.ParameterDescriptor; 008 import org.apache.commons.contract.descriptor.RequiredEnvironmentDescriptor; 009 import org.apache.commons.contract.descriptor.ResultDescriptor; 010 import org.apache.commons.contract.descriptor.ResultEntryDescriptor; 011 import org.apache.commons.i18n.XMLMessageProvider; 012 import org.apache.commons.i18n.bundles.ErrorBundle; 013 014 public class Executor { 015 static { 016 // FIXME - install() method has been removed 017 //XMLMessageProvider.install("contract/exceptions", Thread.currentThread().getContextClassLoader().getResourceAsStream("exceptions.xml")); 018 //XMLMessageProvider.install("contract/constraints", Thread.currentThread().getContextClassLoader().getResourceAsStream("constraints.xml")); 019 } 020 021 public static void init() {}; 022 023 public static Result process(Processor processor, Map parameters, Context context) throws Exception { 024 prepareValues(processor.getParameterDescriptors(), parameters, context); 025 if ( processor instanceof EnvironmentConsumer ) { 026 checkRequirements((EnvironmentConsumer)processor, context); 027 } 028 Result result = processor.process(parameters, context); 029 validateResult(processor.getResultDescriptors(), result, context); 030 return result; 031 } 032 033 public static void prepareValues(ParameterDescriptor[] parameterDescriptors, Map parameters, Context context) throws ContractViolationException { 034 for ( int i = 0; i < parameterDescriptors.length; i++ ) { 035 String parameterName = parameterDescriptors[i].getName(); 036 Object parameterValue = parameters.get(parameterName); 037 Object preparedValue = prepareValue(parameterDescriptors[i], parameterValue, context); 038 parameters.put(parameterName, preparedValue); 039 } 040 } 041 042 public static Object prepareValue(ParameterDescriptor parameterDescriptor, Object value, Context context) throws ContractViolationException { 043 Object preparedValue; 044 if ( value == null ) { 045 if ( parameterDescriptor.isRequired() ) { 046 throw new ContractViolationException(new ErrorBundle("requiredParameterMissing", new String[] { parameterDescriptor.getName() })); 047 } else { 048 preparedValue = parameterDescriptor.getDefaultValue(); 049 } 050 } else { 051 try { 052 preparedValue = parameterDescriptor.getConstraints().cast(value, context); 053 parameterDescriptor.getConstraints().validate(preparedValue, context); 054 } catch ( ContractViolationException exception ) { 055 throw new ContractViolationException(new ErrorBundle("invalidParameter", new Object[] { parameterDescriptor.getName() }), exception); 056 } 057 } 058 return preparedValue; 059 } 060 061 public static void checkRequirements(EnvironmentConsumer processor, Context context) throws ContractViolationException { 062 RequiredEnvironmentDescriptor[] requirementDescriptor = processor.getRequiredEnvironmentDescriptors(); 063 for ( int i = 0; i < requirementDescriptor.length; i++ ) { 064 Store store = context.getStore(requirementDescriptor[i].getStore()); 065 try { 066 Object value = store.get(requirementDescriptor[i].getName(), context); 067 if ( value == null ) { 068 if ( requirementDescriptor[i].isRequired() ) { 069 throw new ValidationException(new ErrorBundle("requiredContextMissing", new Object[] { requirementDescriptor[i].getName(), requirementDescriptor[i].getStore()})); 070 } else { 071 value = requirementDescriptor[i].getDefaultValue(); 072 store.put(requirementDescriptor[i].getName(), value, context); 073 } 074 } 075 Object castedValue = requirementDescriptor[i].getConstraints().cast(value, context); 076 requirementDescriptor[i].getConstraints().validate(castedValue, context); 077 if ( castedValue != value ) { 078 store.put(requirementDescriptor[i].getName(), castedValue, context); 079 } 080 } catch ( StoreException exception ) { 081 throw new ContractViolationException(new ErrorBundle("storeUnaccessable", new Object[] { requirementDescriptor[i].getName(), requirementDescriptor[i].getStore()})); 082 } 083 } 084 } 085 086 087 public static void validateResult(ResultDescriptor[] resultDescriptors, Result result, Context context) throws ContractViolationException { 088 ResultEntryDescriptor []entryDescriptors = getResultDescriptorByState(resultDescriptors, result.getState()).getResultEntryDescriptors(); 089 Map resultEntries = result.getResultEntries(); 090 String name = null; 091 Object value = null; 092 try { 093 for ( int i = 0; i < entryDescriptors.length; i++ ) { 094 ResultEntryDescriptor entryDescriptor = entryDescriptors[i]; 095 name = entryDescriptor.getName(); 096 value = resultEntries.get(name); 097 if ( value == null ) throw new ContractViolationException(new ErrorBundle("missingResultEntry", new String[] { name })); 098 Constraints constraints = entryDescriptor.getConstraints(); 099 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 }