/* * Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") * $Id: ElementContextFlowGeneration.java 3917 2008-04-14 16:55:14Z gbevin $ */ package com.uwyn.rife.engine; import com.uwyn.rife.engine.exceptions.*; import com.uwyn.rife.tools.StringUtils; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; abstract class ElementContextFlowGeneration { static String generateExitUrl(ElementContext context, FlowLink flowlink, String pathInfo) throws EngineException { assert flowlink != null; String url = null; String pathinfo = null; ElementExecutionState element_state = context.getElementState(); // obtain the declared flowlink target element and determine what the // actual target element is according to the inheritance status ElementInfo flowlink_target = flowlink.getExitTarget(context.getRequestState()); ElementInfo context_target = null; if (element_state.inInheritanceStructure() && !flowlink.cancelInheritance()) { context_target = context.getRequestState().getTarget(); } else { context_target = flowlink_target; } url = context_target.getUrl(); // if the element defined no url and the flowlink target points to the element // itself when it's embedded, go up the hierarchy of embedded elements // to grab the first defined element url if (null == url) { if (!context.getRequestState().isEmbedded() && !flowlink_target.getId().equals(context.getElementInfo().getId())) { throw new ExitTargetUrlMissingException(context.getElementInfo().getDeclarationName(), flowlink.getExitName(), context_target.getDeclarationName()); } ElementContext embedding_context = context; while (null == url && embedding_context.getRequestState().isEmbedded()) { embedding_context = embedding_context.getRequestState().getEmbeddingContext().getElementContext(); if (embedding_context.getElementInfo().isPathInfoUsed()) { pathinfo = embedding_context.getRequestState().getElementState().getPathInfo(); } else { pathinfo = null; } if (embedding_context.getElementState().inInheritanceStructure()) { url = embedding_context.getRequestState().getTarget().getUrl(); } else { url = embedding_context.getElementInfo().getUrl(); } } } // apply a forced pathinfo if (pathInfo != null && pathInfo.length() > 0) { pathinfo = pathInfo; } // construct the correct servlet path and url that points to the // target child element, or the current element if there are no children StringBuilder url_buffer = new StringBuilder(context.getRequestState().getGateUrl()); appendTargetAndPathinfo(url_buffer, url, pathinfo); return url_buffer.toString(); } static CharSequenceDeferred generateExitQueryUrl(ElementContext context, FlowLink flowlink, String pathinfo, Map<String, String[]> outputValueMap, String[] outputValues) throws EngineException { assert flowlink != null; ElementInfo flowlink_target = flowlink.getExitTarget(context.getRequestState()); // process the exit url query parameters StateStore state_store = flowlink_target.getStateStore(); FlowState state = context.collectExitParameters(flowlink, outputValueMap, outputValues); // process the pathinfo mappings if (null == pathinfo && flowlink_target.isPathInfoUsed()) { pathinfo = handlePathInfoMapping(flowlink_target, state); } return new CharSequenceQueryUrl(state_store, generateExitUrl(context, flowlink, pathinfo), state, context.getElementInfo(), "exit", flowlink.getExitName()); } static CharSequenceDeferred generateExitFormUrl(ElementContext context, FlowLink flowlink, String pathinfo, Map<String, String[]> outputValueMap) throws EngineException { assert flowlink != null; ElementInfo flowlink_target = flowlink.getExitTarget(context.getRequestState()); StateStore state_store = flowlink_target.getStateStore(); // process the pathinfo mappings if (null == pathinfo && flowlink_target.isPathInfoUsed()) { FlowState state = context.collectExitParameters(flowlink, outputValueMap, null); pathinfo = handlePathInfoMapping(flowlink_target, state); } return new CharSequenceFormUrl(state_store, generateExitUrl(context, flowlink, pathinfo)); } static CharSequenceDeferred generateExitFormParameters(ElementContext context, FlowLink flowlink, Map<String, String[]> outputValueMap, String[] outputValues) throws EngineException { assert flowlink != null; ElementInfo flowlink_target = flowlink.getExitTarget(context.getRequestState()); FlowState state = context.collectExitParameters(flowlink, outputValueMap, outputValues); return new CharSequenceFormState(flowlink_target.getStateStore(), state, FormStateType.PARAMS); } static CharSequenceDeferred generateExitFormParametersJavascript(ElementContext context, FlowLink flowlink, Map<String, String[]> outputValueMap, String[] outputValues) throws EngineException { assert flowlink != null; ElementInfo flowlink_target = flowlink.getExitTarget(context.getRequestState()); FlowState state = context.collectExitParameters(flowlink, outputValueMap, outputValues); return new CharSequenceFormState(flowlink_target.getStateStore(), state, FormStateType.JAVASCRIPT); } static String generateSubmissionUrl(ElementContext context, String pathInfo) { ElementExecutionState element_state = context.getElementState(); String url = null; String pathinfo = null; ElementInfo element_info = null; if (element_state.inInheritanceStructure()) { element_info = context.getRequestState().getTarget(); } else { element_info = context.getElementInfo(); } url = element_info.getUrl(); if (element_info.isPathInfoUsed()) { pathinfo = context.getRequestState().getElementState().getPathInfo(); } // if the element defined no url, go up the hierarchy of embedded elements // to grab the first defined element url if (null == url) { if (!context.getRequestState().isEmbedded()) { if (element_state.inInheritanceStructure()) { throw new SubmissionInheritanceUrlMissingException(context.getRequestState().getTarget().getDeclarationName(), context.getElementInfo().getDeclarationName()); } else { throw new SubmissionUrlMissingException(context.getElementInfo().getDeclarationName()); } } ElementContext embedding_context = context; while (null == url && embedding_context.getRequestState().isEmbedded()) { embedding_context = embedding_context.getRequestState().getEmbeddingContext().getElementContext(); ElementInfo context_element_info = null; if (embedding_context.getElementState().inInheritanceStructure()) { context_element_info = embedding_context.getRequestState().getTarget(); } else { context_element_info = embedding_context.getElementInfo(); } url = context_element_info.getUrl(); if (context_element_info.isPathInfoUsed()) { pathinfo = embedding_context.getRequestState().getElementState().getPathInfo(); } } } // apply a forced pathinfo if (pathInfo != null && pathInfo.length() > 0) { pathinfo = pathInfo; } // construct the correct servlet path and url that points to the // target child element, or the current element if there are no children StringBuilder url_buffer = new StringBuilder(context.getRequestState().getGateUrl()); appendTargetAndPathinfo(url_buffer, url, pathinfo); return url_buffer.toString(); } static CharSequenceDeferred generateSubmissionQueryUrl(ElementContext context, String name, String pathinfo, String[] parameterValues, Set<Map.Entry<String, String[]>> outputEntries) throws EngineException { StateStore state_store = context.getElementInfo().getStateStore(); FlowState state = context.collectSubmissionParameters(name, parameterValues, outputEntries); return new CharSequenceQueryUrl(state_store, generateSubmissionUrl(context, pathinfo), state, context.getElementInfo(), "submission", name); } static CharSequenceDeferred generateSubmissionFormUrl(ElementContext context, String pathinfo) throws EngineException { return new CharSequenceFormUrl(context.getElementInfo().getStateStore(), generateSubmissionUrl(context, pathinfo)); } static CharSequenceDeferred generateSubmissionFormParameters(ElementContext context, String name, String[] parameterValues, Set<Map.Entry<String, String[]>> outputEntries) throws EngineException { FlowState state = context.collectSubmissionParameters(name, parameterValues, outputEntries); return new CharSequenceFormState(context.getElementInfo().getStateStore(), state, FormStateType.PARAMS); } static CharSequenceDeferred generateSubmissionFormParametersJavascript(ElementContext context, String name, String[] parameterValues, Set<Map.Entry<String, String[]>> outputEntries) throws EngineException { FlowState state = context.collectSubmissionParameters(name, parameterValues, outputEntries); return new CharSequenceFormState(context.getElementInfo().getStateStore(), state, FormStateType.JAVASCRIPT); } private static String handlePathInfoMapping(ElementInfo flowlinkTarget, FlowState state) { Map<String, String[]> parameters = state.getParameters(); mapping: for (PathInfoMapping mapping : flowlinkTarget.getPathInfoMappings()) { if (parameters.keySet().containsAll(mapping.getInputs())) { Iterator<String> inputs_it = mapping.getInputs().iterator(); StringBuilder builder = new StringBuilder(); String input_name; String[] input_value; for (PathInfoMappingSegment segment : mapping.getSegments()) { if (segment.isRegexp()) { if (!inputs_it.hasNext()) { continue mapping; } input_name = inputs_it.next(); // ensure that the input has only got one value input_value = parameters.get(input_name); if (null == input_value || input_value.length != 1) { continue mapping; } // ensure that the input value corresponds to the // regexp pattern for it Matcher matcher = segment.getPattern().matcher(input_value[0]); if (!matcher.matches()) { continue mapping; } // add the url-encoded input value to the pathinfo builder.append(StringUtils.encodeUrl(input_value[0])); } else { builder.append(segment.getValue()); } } // remove the input parameters that are handled by the pathinfo for (String input : mapping.getInputs()) { parameters.remove(input); } // build the new pathinfo return builder.toString(); } } return null; } private static void appendTargetAndPathinfo(StringBuilder url, String targetUrl, String pathinfo) { url.append(targetUrl); // append the optional pathinfo if (pathinfo != null && pathinfo.length() > 0) { // ensure that the pathinfo is prefixed with a / if (url.charAt(url.length()-1) != '/') { url.append("/"); } url.append(StringUtils.stripFromFront(pathinfo, "/")); } } }