/**
* Copyright 2005-2016 hdiv.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hdiv.web.servlet.support;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.hdiv.context.RequestContextDataValueProcessor;
import org.hdiv.context.RequestContextHolder;
import org.hdiv.dataComposer.IDataComposer;
import org.hdiv.urlProcessor.FormUrlProcessor;
import org.hdiv.urlProcessor.LinkUrlProcessor;
import org.hdiv.util.HDIVUtil;
import org.hdiv.util.Method;
import org.springframework.web.servlet.support.RequestDataValueProcessor;
/**
* {@link RequestDataValueProcessor} implementation for HDIV.
*
* @author Gotzon Illarramendi
*/
public class HdivRequestDataValueProcessor implements RequestDataValueProcessor, RequestContextDataValueProcessor {
protected LinkUrlProcessor linkUrlProcessor;
protected FormUrlProcessor formUrlProcessor;
/**
* Inner delegate {@link RequestDataValueProcessor} implementation. Only works with Spring greater or equal to 4.0.0.
*/
protected RequestDataValueProcessor innerRequestDataValueProcessor;
/**
* No editable field types.
*/
protected Set<String> noEditableTypes = new HashSet<String>();
public HdivRequestDataValueProcessor() {
// Initialize no editable types list
initNoEditableTypes();
}
/**
* <p>
* Initialize no editable input types.
* </p>
* Non editable input types:
* <ul>
* <li>checkbox</li>
* <li>hidden</li>
* <li>option</li>
* <li>radio</li>
* <li>select</li>
* <li>submit</li>
* </ul>
* Editable input types:
* <ul>
* <li>text</li>
* <li>textarea</li>
* <li>password</li>
* <li>other input types: (number, tel, email...)</li>
* </ul>
*/
protected void initNoEditableTypes() {
noEditableTypes.add("checkbox");
noEditableTypes.add("hidden");
noEditableTypes.add("option");
noEditableTypes.add("radio");
noEditableTypes.add("select");
noEditableTypes.add("submit");
}
/**
* Process the action url of the form tag, maintained for legacy support Spring 3.1.x.
*
* @param request request object
* @param action form action url
* @return processed action url
*/
public String processAction(final HttpServletRequest request, final String action) {
return this.processAction(request, action, Method.POST.toString());
}
@Deprecated
public final String processAction(final HttpServletRequest request, final String action, final String method) {
return processAction(HDIVUtil.getRequestContext(request), action, method);
}
@Deprecated
public final String processFormFieldValue(final HttpServletRequest request, final String name, final String value, final String type) {
return processFormFieldValue(HDIVUtil.getRequestContext(request), name, value, type);
}
@Deprecated
public final Map<String, String> getExtraHiddenFields(final HttpServletRequest request) {
return getExtraHiddenFields(HDIVUtil.getRequestContext(request));
}
@Deprecated
public final String processUrl(final HttpServletRequest request, final String url) {
return processUrl(HDIVUtil.getRequestContext(request), url);
}
/**
* Get extra hidden fields from the inner {@link RequestDataValueProcessor}.
*
* @param request request object
* @return hidden field name/value
*/
protected final Map<String, String> getInnerExtraHiddenFields(final HttpServletRequest request) {
Map<String, String> extraFields = new HashMap<String, String>();
if (innerRequestDataValueProcessor != null) {
Map<String, String> innerExtras = innerRequestDataValueProcessor.getExtraHiddenFields(request);
if (innerExtras != null) {
extraFields.putAll(innerExtras);
}
}
return extraFields;
}
/**
* Determines if a field type is editable or not.
*
* @param type field type
* @return editable
*/
protected boolean isEditable(final String type) {
return !noEditableTypes.contains(type);
}
/**
* @param linkUrlProcessor the linkUrlProcessor to set
*/
public void setLinkUrlProcessor(final LinkUrlProcessor linkUrlProcessor) {
this.linkUrlProcessor = linkUrlProcessor;
}
/**
* @param formUrlProcessor the formUrlProcessor to set
*/
public void setFormUrlProcessor(final FormUrlProcessor formUrlProcessor) {
this.formUrlProcessor = formUrlProcessor;
}
/**
* @param innerRequestDataValueProcessor the innerRequestDataValueProcessor to set
*/
public void setInnerRequestDataValueProcessor(final RequestDataValueProcessor innerRequestDataValueProcessor) {
this.innerRequestDataValueProcessor = innerRequestDataValueProcessor;
}
/**
* @return the innerRequestDataValueProcessor
*/
public RequestDataValueProcessor getInnerRequestDataValueProcessor() {
return innerRequestDataValueProcessor;
}
public String processAction(final RequestContextHolder request, String action, final String method) {
if (innerRequestDataValueProcessor != null) {
@SuppressWarnings("deprecation")
String processedAction = innerRequestDataValueProcessor.processAction(request.getRequest(), action, method);
if (processedAction != action) {
action = processedAction;
}
}
return formUrlProcessor.processUrl(request, action, Method.secureValueOf(method));
}
public String processFormFieldValue(final RequestContextHolder request, final String name, String value, final String type) {
if (innerRequestDataValueProcessor != null) {
@SuppressWarnings("deprecation")
String processedValue = innerRequestDataValueProcessor.processFormFieldValue(request.getRequest(), name, value, type);
if (processedValue != value) {
value = processedValue;
}
}
if (name == null) {
return value;
}
IDataComposer dataComposer = request.getDataComposer();
if (dataComposer == null) {
return value;
}
if (isEditable(type)) {
dataComposer.composeFormField(name, value, true, type);
return value;
}
else {
return dataComposer.composeFormField(name, value, false, type);
}
}
public Map<String, String> getExtraHiddenFields(final RequestContextHolder context) {
@SuppressWarnings("deprecation")
Map<String, String> extraFields = getInnerExtraHiddenFields(context.getRequest());
IDataComposer dataComposer = context.getDataComposer();
if (dataComposer == null || !dataComposer.isRequestStarted()) {
return extraFields;
}
String requestId = dataComposer.endRequest();
if (requestId != null && requestId.length() > 0) {
String hdivStateParam = dataComposer.getHdivParameterName();
if (hdivStateParam != null) {
extraFields.put(hdivStateParam, requestId);
}
// Publish the state in request to make it accessible on jsp
context.setFormStateId(requestId);
}
return extraFields;
}
public String processUrl(final RequestContextHolder request, String url) {
if (innerRequestDataValueProcessor != null) {
@SuppressWarnings("deprecation")
String processedUrl = innerRequestDataValueProcessor.processUrl(request.getRequest(), url);
if (processedUrl != null) {
url = processedUrl;
}
}
return linkUrlProcessor.processUrl(request, url);
}
}