1 package org.apache.slide.projector.processor.form; 2 3 import java.util.ArrayList ; 4 import java.util.HashMap ; 5 import java.util.Iterator ; 6 import java.util.List ; 7 import java.util.Locale ; 8 import java.util.Map ; 9 10 import org.apache.slide.projector.ConfigurationException; 11 import org.apache.slide.projector.Context; 12 import org.apache.slide.projector.Information; 13 import org.apache.slide.projector.ProcessException; 14 import org.apache.slide.projector.Processor; 15 import org.apache.slide.projector.Result; 16 import org.apache.slide.projector.Store; 17 import org.apache.slide.projector.URI; 18 import org.apache.slide.projector.descriptor.ArrayValueDescriptor; 19 import org.apache.slide.projector.descriptor.BooleanValueDescriptor; 20 import org.apache.slide.projector.descriptor.LocaleValueDescriptor; 21 import org.apache.slide.projector.descriptor.MapValueDescriptor; 22 import org.apache.slide.projector.descriptor.ParameterDescriptor; 23 import org.apache.slide.projector.descriptor.ResultDescriptor; 24 import org.apache.slide.projector.descriptor.ResultEntryDescriptor; 25 import org.apache.slide.projector.descriptor.StateDescriptor; 26 import org.apache.slide.projector.descriptor.StringValueDescriptor; 27 import org.apache.slide.projector.descriptor.URIValueDescriptor; 28 import org.apache.slide.projector.descriptor.ValidationException; 29 import org.apache.slide.projector.engine.ProcessorManager; 30 import org.apache.slide.projector.i18n.DefaultMessage; 31 import org.apache.slide.projector.i18n.ErrorMessage; 32 import org.apache.slide.projector.i18n.MessageNotFoundException; 33 import org.apache.slide.projector.i18n.ParameterMessage; 34 import org.apache.slide.projector.processor.SimpleProcessor; 35 import org.apache.slide.projector.processor.TemplateRenderer; 36 import org.apache.slide.projector.processor.process.Process; 37 import org.apache.slide.projector.store.FormStore; 38 import org.apache.slide.projector.value.ArrayValue; 39 import org.apache.slide.projector.value.BooleanValue; 40 import org.apache.slide.projector.value.LocaleValue; 41 import org.apache.slide.projector.value.MapValue; 42 import org.apache.slide.projector.value.NullValue; 43 import org.apache.slide.projector.value.StreamableValue; 44 import org.apache.slide.projector.value.StringValue; 45 import org.apache.slide.projector.value.URIValue; 46 import org.apache.slide.projector.value.Value; 47 48 52 public class ControlComposer extends TemplateRenderer { 53 public final static String VALIDATE = "validate"; 55 public final static String LOCALE = "locale"; 56 public final static String ACTION = "action"; 57 public final static String ERRORS_PROCESSOR = "errorsProcessor"; 58 public final static String CONTROL_DESCRIPTIONS = "controlDescriptions"; 59 public final static String TRIGGER_DESCRIPTIONS = "triggerDescriptions"; 60 61 public final static String CONTROL = "control"; 63 public final static String CONTROL_NAME = "controlName"; 64 public final static String CONTROL_CONTAINER = "controlContainer"; 65 66 public final static String TRIGGER = "trigger"; 67 public final static String TRIGGER_NAME = "triggerName"; 68 public final static String TRIGGER_CONTAINER = "triggerContainer"; 69 70 protected final static String TITLE = "title"; 72 protected final static String TEXT = "text"; 73 protected final static String PROMPT = "prompt"; 74 protected final static String ERRORS = "errors"; 75 protected final static String ERRORS_TITLE = "errors-title"; 76 77 public final static String ERROR_NUMBER = "error-number"; 78 public final static String ERROR_TITLE = "error-title"; 79 public final static String ERROR_TEXT = "error-text"; 80 public final static String ERROR_DETAILS = "error-details"; 81 public final static String ERROR_SUMMARY = "error-summary"; 82 83 public final static String GENERATED_CONTROLS = "renderedControls"; 85 public final static String GENERATED_TRIGGERS = "renderedTriggers"; 86 public final static String RENDERED_ERRORS = "renderedErrors"; 87 public final static String DEFAULT_STATE ="default"; 88 public final static String VALID_STATE ="valid"; 89 public final static String INVALID_STATE ="invalid"; 90 91 public final static String HANDLER = "handler"; 93 public final static String METHOD = "method"; 94 95 protected final static String DEFAULT_FORM = "default form"; 96 protected final static String INVALID_FORM = "invalid form"; 97 protected final static String VALID_FORM = "valid form"; 98 99 protected final static String GET = "GET"; 100 protected final static String POST = "POST"; 101 protected final static String [] methods = new String [] { GET, POST }; 102 103 protected Template defaultTemplate; 104 protected Template validTemplate; 105 protected Template invalidTemplate; 106 107 protected ErrorMessage NO_ERROR_MESSAGE_AVAILABLE = new ErrorMessage("errorMessageNotFound"); 108 protected ParameterMessage NO_PARAMETER_MESSAGE_AVAILABLE = new ParameterMessage("parameterMessageNotFound"); 109 110 private ParameterDescriptor[] parameterDescriptors; 111 112 public ControlComposer() { 113 setRequiredFragments(new String [] { DEFAULT_FORM }); 114 setOptionalFragments(new String [] { VALID_FORM, INVALID_FORM }); 115 } 116 117 private final static ResultDescriptor resultDescriptor = new ResultDescriptor( 118 new StateDescriptor[] { 119 new StateDescriptor(DEFAULT_STATE, new DefaultMessage("controlComposer/state/default")), 120 new StateDescriptor(VALID_STATE, new DefaultMessage("controlComposer/state/valid")), 121 new StateDescriptor(INVALID_STATE, new DefaultMessage("controlComposer/state/invalid")) 122 }, 123 new ResultEntryDescriptor[]{ 124 new ResultEntryDescriptor(GENERATED_CONTROLS, new DefaultMessage("controlComposer/generatedControls"), ArrayValue.CONTENT_TYPE, false), 125 new ResultEntryDescriptor(GENERATED_TRIGGERS, new DefaultMessage("controlComposer/generatedTriggers"), ArrayValue.CONTENT_TYPE, false), 126 new ResultEntryDescriptor(RENDERED_ERRORS, new DefaultMessage("controlComposer/renderedErrors"), MapValue.CONTENT_TYPE, false) 127 }); 128 129 public void configure(StreamableValue config) throws ConfigurationException { 130 super.configure(config); 131 ParameterDescriptor[] parentParameterDescriptors = super.getParameterDescriptors(); 132 parameterDescriptors = new ParameterDescriptor[parentParameterDescriptors.length + 5]; 133 System.arraycopy(parentParameterDescriptors, 0, parameterDescriptors, 0, parentParameterDescriptors.length); 134 parameterDescriptors[parentParameterDescriptors.length] = 135 new ParameterDescriptor(CONTROL_DESCRIPTIONS, new ParameterMessage("controlComposer/controlDescriptions"), new ArrayValueDescriptor( 136 new MapValueDescriptor(new ParameterDescriptor[] { 137 new ParameterDescriptor(Control.ACTION, new ParameterMessage("controlComposer/controlDescriptions/action"), new URIValueDescriptor(), NullValue.NULL), 138 new ParameterDescriptor(CONTROL, new ParameterMessage("controlComposer/controlDescriptions/control"), new URIValueDescriptor()), 139 new ParameterDescriptor(CONTROL_CONTAINER, new ParameterMessage("controlComposer/controlDescriptions/controlContainer"), new URIValueDescriptor(), NullValue.NULL), 140 }))); 141 parameterDescriptors[parentParameterDescriptors.length+1] = 142 new ParameterDescriptor(TRIGGER_DESCRIPTIONS, new ParameterMessage("controlComposer/triggerDescriptions"), new ArrayValueDescriptor( 143 new MapValueDescriptor(new ParameterDescriptor[] { 144 new ParameterDescriptor(Trigger.ACTION, new ParameterMessage("controlComposer/triggerDescriptions/action"), new URIValueDescriptor(), NullValue.NULL), 145 new ParameterDescriptor(Trigger.VALIDATE, new ParameterMessage("controlComposer/triggerDescriptions/validate"), new BooleanValueDescriptor(), BooleanValue.TRUE), 146 new ParameterDescriptor(Trigger.INVOLVED_PARAMETERS, new ParameterMessage("trigger/involvedParameters"), new ArrayValueDescriptor(new StringValueDescriptor()), NullValue.NULL), 147 new ParameterDescriptor(Process.STEP, new ParameterMessage("controlComposer/triggerDescriptions/step"), new StringValueDescriptor()), 148 new ParameterDescriptor(TRIGGER, new ParameterMessage("controlComposer/triggerDescriptions/trigger"), new URIValueDescriptor()), 149 new ParameterDescriptor(TRIGGER_CONTAINER, new ParameterMessage("controlComposer/triggerDescriptions/triggerContainer"), new URIValueDescriptor(), NullValue.NULL) 150 }))); 151 parameterDescriptors[parentParameterDescriptors.length+2] = 152 new ParameterDescriptor(LOCALE, new ParameterMessage("controlComposer/locale"), new LocaleValueDescriptor()); 153 parameterDescriptors[parentParameterDescriptors.length+3] = 154 new ParameterDescriptor(ACTION, new ParameterMessage("controlComposer/action"), new URIValueDescriptor()); 155 parameterDescriptors[parentParameterDescriptors.length+4] = 156 new ParameterDescriptor(ERRORS_PROCESSOR, new ParameterMessage("controlComposer/errorsProcessor"), new URIValueDescriptor(), NullValue.NULL); 157 158 try { 159 defaultTemplate = getRequiredFragment(DEFAULT_FORM); 160 } catch ( ProcessException exception ) { 161 throw new ConfigurationException(new ErrorMessage("form/defaultFragmentMissing")); 162 } 163 validTemplate = getOptionalFragment(VALID_FORM); 164 invalidTemplate = getOptionalFragment(INVALID_FORM); 165 } 166 167 public Result process(Map parameter, Context context) throws Exception { 168 Value[] controlDescriptions = ((ArrayValue)parameter.get(CONTROL_DESCRIPTIONS)).getArray(); 169 Value[] triggerDescriptions = ((ArrayValue)parameter.get(TRIGGER_DESCRIPTIONS)).getArray(); 170 URI actionUri = (URIValue)parameter.get(ACTION); 171 Value errorsProcessorUri = (Value)parameter.get(ERRORS_PROCESSOR); 172 Locale locale = ((LocaleValue)parameter.get(LOCALE)).getLocale(); 173 String state = DEFAULT_STATE; 174 List informations = context.getInformations(); 175 MapValue mapResource = (MapValue)((FormStore)context.getStore(Store.FORM)).getDomain(); 176 List generatedControls = new ArrayList (); 177 List involvedParameters = new ArrayList (); 178 for (int i = 0; i < controlDescriptions.length; i++ ) { 179 Map controlParameters = ((MapValue)controlDescriptions[i]).getMap(); 180 String controlName = controlParameters.get(CONTROL_NAME).toString(); 181 URI controlUri = (URI)controlParameters.get(CONTROL); 182 Control control = (Control)ProcessorManager.getInstance().getProcessor(controlUri); 183 Value controlActionUri = (Value)controlParameters.get(Control.ACTION); 184 if ( controlActionUri == NullValue.NULL ) controlActionUri = actionUri; 185 controlParameters.put(Control.ACTION, controlActionUri); 186 try { 187 ProcessorManager.prepareValues(control.getParameterDescriptors(), controlParameters, context); 188 } catch ( ValidationException exception ) { 189 throw new ValidationException(new ErrorMessage("controlComposer/controlParameterInvalid", new Object [] { controlUri }), exception); 190 } 191 Value controlContainerUri = (Value)controlParameters.get(CONTROL_CONTAINER); 192 ParameterDescriptor parameterDescriptor = Control.getParameterDescriptor(controlParameters, context); 193 String parameterName = parameterDescriptor.getName(); 194 involvedParameters.add(new StringValue(parameterName)); 195 ParameterMessage description = (ParameterMessage)parameterDescriptor.getDescription(); 196 boolean required = parameterDescriptor.isRequired(); 197 String controlState = Control.OPTIONAL_CONTROL; 198 if ( required ) { 199 controlState = Control.REQUIRED_CONTROL; 200 } 201 Object controlValue = null; 202 boolean validate = false; 203 if ( mapResource != null ) { 204 controlValue = mapResource.getMap().get(parameterName); 205 validate = false; 206 BooleanValue validateResource = ((BooleanValue)mapResource.getMap().get(VALIDATE)); 207 if ( validateResource != null ) validate = validateResource.booleanValue(); 208 } 209 if ( validate ) { 210 try { 211 controlValue = ProcessorManager.prepareValue(parameterDescriptor, controlValue, context); 212 } catch ( ValidationException exception ) { 213 controlValue = StringValueDescriptor.ANY.valueOf(controlValue, context).toString(); 214 context.addInformation(new Information(Information.ERROR, exception.getErrorMessage(), new String [] { parameterName })); 215 } 216 controlParameters.put(Control.VALUE, controlValue); 217 if ( hasErrors(informations, parameterName) ) { 218 if ( required ) { 219 controlState = Control.REQUIRED_INVALID_CONTROL; 220 } else { 221 controlState = Control.OPTIONAL_INVALID_CONTROL; 222 } 223 explodeInformations(controlParameters, informations, parameterName, locale); 224 } else { 225 if ( required ) { 226 controlState = Control.REQUIRED_VALID_CONTROL; 227 } else { 228 controlState = Control.OPTIONAL_VALID_CONTROL; 229 } 230 } 231 } 232 controlParameters.put(Control.STATE, controlState); 233 controlParameters.put(Control.VALUE, controlValue); 234 Result controlResult = control.process(controlParameters, context); 235 if ( controlContainerUri != NullValue.NULL ) { 236 Processor controlContainer = ProcessorManager.getInstance().getProcessor((URI)controlContainerUri); 237 Map controlContainerParameters = new HashMap (); 238 controlContainerParameters.putAll(parameter); 239 if ( hasErrors(informations, parameterName) ) { 240 explodeInformations(controlContainerParameters, informations, parameterName, locale); 241 } 242 controlContainerParameters.put(Control.STATE, controlState); 243 controlContainerParameters.put(CONTROL, controlResult.getResultEntries().get(OUTPUT)); 244 controlContainerParameters.put(TITLE, description.getTitle(locale, parameterName )); 245 try { 246 controlContainerParameters.put(TEXT, description.getText(locale)); 247 controlContainerParameters.put(PROMPT, description.getPrompt(locale)); 248 } catch ( MessageNotFoundException exception ) { 249 controlContainerParameters.put(TEXT, NO_PARAMETER_MESSAGE_AVAILABLE.getText(locale, " ")); 250 controlContainerParameters.put(PROMPT, NO_PARAMETER_MESSAGE_AVAILABLE.getPrompt(locale, " ")); 251 } 252 try { 253 ProcessorManager.prepareValues(controlContainer.getParameterDescriptors(), controlContainerParameters, context); 254 } catch ( ValidationException exception ) { 255 throw new ValidationException(new ErrorMessage("controlComposer/controlContainerParameterInvalid", new Object [] { controlContainerUri }), exception); 256 } 257 Result controlContainerResult = controlContainer.process(controlContainerParameters, context); 258 generatedControls.add(new MapValue(controlName, (Value)controlContainerResult.getResultEntries().get(OUTPUT))); 259 } else { 260 generatedControls.add(new MapValue(controlName, (Value)controlResult.getResultEntries().get(OUTPUT))); 261 } 262 if ( controlState == Control.OPTIONAL_INVALID_CONTROL || controlState == Control.REQUIRED_INVALID_CONTROL ) { 263 state = INVALID_STATE; 264 } else if ( state == DEFAULT_STATE && ( controlState == Control.OPTIONAL_VALID_CONTROL || controlState == Control.REQUIRED_VALID_CONTROL ) ) { 265 state = VALID_STATE; 266 } 267 } 268 Result composerResult = new Result(state, GENERATED_CONTROLS, new ArrayValue((Value [])generatedControls.toArray(new Value[generatedControls.size()]))); 269 List generatedTriggers = new ArrayList (); 270 for (int i = 0; i < triggerDescriptions.length; i++ ) { 271 Map triggerParameters = ((MapValue)triggerDescriptions[i]).getMap(); 272 String triggerName = triggerParameters.get(TRIGGER_NAME).toString(); 273 Value involvedTriggerParameters = (Value)triggerParameters.get(Trigger.INVOLVED_PARAMETERS); 274 if ( involvedTriggerParameters == NullValue.NULL ) { 275 involvedTriggerParameters = new ArrayValue((StringValue[])involvedParameters.toArray(new StringValue[involvedParameters.size()])); 276 } 277 triggerParameters.put(Trigger.INVOLVED_PARAMETERS, involvedTriggerParameters); 278 URI triggerUri = (URI)triggerParameters.get(TRIGGER); 279 Trigger trigger = (Trigger)ProcessorManager.getInstance().getProcessor(triggerUri); 280 Value triggerActionUri = (Value)triggerParameters.get(Trigger.ACTION); 281 if ( triggerActionUri == NullValue.NULL ) triggerActionUri = actionUri; 282 triggerParameters.put(Trigger.ACTION, triggerActionUri); 283 try { 284 ProcessorManager.prepareValues(trigger.getParameterDescriptors(), triggerParameters, context); 285 } catch ( ValidationException exception ) { 286 throw new ValidationException(new ErrorMessage("controlComposer/triggerParameterInvalid", new Object [] { triggerUri }), exception); 287 } 288 Value triggerContainerUri = (Value)triggerParameters.get(TRIGGER_CONTAINER); 289 Result triggerResult = trigger.process(triggerParameters, context); 290 if ( triggerContainerUri != NullValue.NULL ) { 291 Processor triggerContainer = ProcessorManager.getInstance().getProcessor((URI)triggerContainerUri); 292 Map triggerContainerParameters = new HashMap (); 293 triggerContainerParameters.putAll(parameter); 294 triggerContainerParameters.put(TRIGGER, triggerResult.getResultEntries().get(OUTPUT)); 295 try { 296 ProcessorManager.prepareValues(triggerContainer.getParameterDescriptors(), triggerContainerParameters, context); 297 } catch ( ValidationException exception ) { 298 throw new ValidationException(new ErrorMessage("controlComposer/triggerContainerParameterInvalid", new Object [] { triggerContainerUri }), exception); 299 } 300 Result triggerContainerResult = triggerContainer.process(triggerContainerParameters, context); 301 generatedTriggers.add(new MapValue(triggerName, (Value)triggerContainerResult.getResultEntries().get(OUTPUT))); 302 } else { 303 generatedTriggers.add(new MapValue(triggerName, (Value)triggerResult.getResultEntries().get(OUTPUT))); 304 } 305 } 306 composerResult.addResultEntry(GENERATED_TRIGGERS, new ArrayValue((Value [])generatedTriggers.toArray(new Value[generatedTriggers.size()]))); 307 if ( errorsProcessorUri instanceof URI ) { 308 Processor errorsTable = ProcessorManager.getInstance().getProcessor((URI)errorsProcessorUri); 309 List errorList = new ArrayList (); 310 for ( Iterator i = context.getInformations().iterator(); i.hasNext(); ) { 311 Information info = (Information)i.next(); 312 Map errors = new HashMap (); 313 explodeInformation(errors, info, locale ); 314 errorList.add(new MapValue(errors)); 315 } 316 Map errorsParameter = new HashMap (); 317 MapValue[] errorsArray = new MapValue[errorList.size()]; 318 errorsParameter.put(SimpleProcessor.INPUT, new ArrayValue((MapValue[])errorList.toArray(errorsArray))); 319 Result renderedErrors = ProcessorManager.process(errorsTable, errorsParameter, context); 320 composerResult.addResultEntry(RENDERED_ERRORS, (Value)renderedErrors.getResultEntries().get(OUTPUT)); 321 } 322 return composerResult; 323 } 324 325 protected void explodeInformations(Map parameters, List informations, String parameterName, Locale locale) { 326 List matchingInfos = getErrors(informations, parameterName); 328 StringBuffer buffer = new StringBuffer (); 329 for ( Iterator i = matchingInfos.iterator(); i.hasNext(); ) { 330 Information info = (Information)i.next(); 331 buffer.append(info.getNumber()).append(") "); 332 explodeInformation(parameters, info, locale); 333 } 334 parameters.put(ERROR_NUMBER, buffer.toString()); 335 } 336 337 protected void explodeInformation(Map parameters, Information info, Locale locale) { 338 parameters.put(ERROR_NUMBER, String.valueOf(info.getNumber())); 339 try { 340 parameters.put(ERROR_TITLE, info.getErrorMessage().getTitle(locale)); 341 parameters.put(ERROR_TEXT, info.getErrorMessage().getText(locale)); 342 parameters.put(ERROR_SUMMARY, info.getErrorMessage().getSummary(locale)); 343 parameters.put(ERROR_DETAILS, info.getErrorMessage().getDetails(locale)); 344 } catch ( MessageNotFoundException exception ) { 345 parameters.put(ERROR_TITLE, NO_ERROR_MESSAGE_AVAILABLE.getTitle(locale, "no error title available")); 346 parameters.put(ERROR_TEXT, NO_ERROR_MESSAGE_AVAILABLE.getText(locale, "no error text available")); 347 parameters.put(ERROR_SUMMARY, NO_ERROR_MESSAGE_AVAILABLE.getSummary(locale, "no error summary available")); 348 parameters.put(ERROR_DETAILS, NO_ERROR_MESSAGE_AVAILABLE.getDetails(locale, "no error details available")); 349 } 350 } 351 352 protected boolean hasErrors(List informations, String parameterName) { 353 for ( Iterator i = informations.iterator(); i.hasNext(); ) { 354 Information info = (Information)i.next(); 355 if ( info.isParameterInvolved(parameterName) && info.getSeverity() == Information.ERROR ) { 356 return true; 357 } 358 } 359 return false; 360 } 361 362 protected List getErrors(List informations, String parameterName) { 363 List matchingInfos = new ArrayList (); 364 for ( Iterator i = informations.iterator(); i.hasNext(); ) { 365 Information info = (Information)i.next(); 366 if ( info.isParameterInvolved(parameterName) && info.getSeverity() == Information.ERROR ) { 367 matchingInfos.add(info); 368 } 369 } 370 return matchingInfos; 371 } 372 373 public ParameterDescriptor[] getParameterDescriptors() { 374 return parameterDescriptors; 375 } 376 377 public ResultDescriptor getResultDescriptor() { 378 return resultDescriptor; 379 } 380 } | Popular Tags |