/*
* Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.entando.entando.plugins.jpwebform.aps.internalservlet.form;
import java.util.Date;
import java.util.List;
import org.entando.entando.plugins.jpwebform.aps.system.services.JpwebformSystemConstants;
import org.entando.entando.plugins.jpwebform.aps.system.services.form.IFormManager;
import org.entando.entando.plugins.jpwebform.aps.system.services.form.IGuiGeneratorManager;
import org.entando.entando.plugins.jpwebform.aps.system.services.message.model.Message;
import org.entando.entando.plugins.jpwebform.aps.system.services.message.model.Step;
import org.entando.entando.plugins.jpwebform.aps.system.services.message.model.StepsConfig;
import org.entando.entando.plugins.jpwebform.aps.system.services.message.model.TypeVersionGuiConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.agiletec.aps.system.RequestContext;
import com.agiletec.aps.system.SystemConstants;
import com.agiletec.aps.system.common.entity.model.IApsEntity;
import com.agiletec.aps.system.common.entity.model.attribute.MonoTextAttribute;
import com.agiletec.aps.system.exception.ApsSystemException;
import com.agiletec.aps.system.services.lang.Lang;
import com.agiletec.aps.system.services.page.Widget;
import com.agiletec.aps.util.ApsProperties;
import com.agiletec.apsadmin.system.entity.AbstractApsEntityAction;
import com.agiletec.plugins.jpmail.aps.services.mail.IMailManager;
/**
* Implementation for action managing Message entity editing operations.
*
* @author E.Mezzano
*/
public class UserFormAction extends AbstractApsEntityAction {
private static final Logger _logger = LoggerFactory.getLogger(UserFormAction.class);
@Override
public void validate() {
if (this.getMessage() != null) {
super.validate();
}
}
@Override
public IApsEntity getApsEntity() {
return this.getMessage();
}
@Override
public String view() {
//Operation not allowed
return null;
}
@Override
public String createNew() {
try {
String typeCode = this.getTypeCode();
TypeVersionGuiConfig configType = null;
Message resumedMessage = resumeMessage();
if (resumedMessage != null) {
configType = this.getMessageManager().getTypeVersionGui(typeCode, resumedMessage.getVersionType());
} else {
configType = this.getMessageManager().getTypeVersionGui(typeCode);
}
if (null == configType) {
_logger.error("configuration GUI is null");
return FAILURE;
}
// create GUI
this.getGuiGeneratorManager().checkUserGuis(configType);
Message prototype = (Message) configType.getPrototype().getEntityPrototype();
Message prototyConfig = (Message) this.getMessageManager().getEntityPrototype(typeCode);
Message existAlready = this.getMessageManager().resumeMessageByUserAndType(this.getCurrentUser().getUsername(), typeCode, new Integer(1));
// if the form exist and was fully completed
if ((null != existAlready && existAlready.isCompleted())
// and it cannot be submitted multiple times
&& (!prototyConfig.isRepeatable()
// and the current is not guest
&& !isGuest())) {
return "notRepeatable";
}
this.setVersionConfigOnSession(configType);
if (null == resumedMessage
|| resumedMessage.isCompleted()
|| isGuest()) {
this.setVersionType(configType.getVersion());
StepsConfig stepsConfig = configType.getStepsConfig();
Step firstStep = stepsConfig.getFirstStep();
this.setCurrentStepCode(firstStep.getCode());
String username = this.getCurrentUser().getUsername();
prototype.setUsername(username);
prototype.setCreationDate(new Date());
prototype.setLangCode(this.getCurrentLang().getCode());
prototype.toggleAttribute(firstStep.getCode());
this.setMessageOnSession(prototype);
} else {
// load latest version of the form
TypeVersionGuiConfig latestType = this.getMessageManager().getTypeVersionGui(typeCode);
// check whether we have to update to the latest version
if (!prototyConfig.isIgnoreVersionEdit()
// version is not changed
|| (prototyConfig.isIgnoreVersionEdit()
&& resumedMessage.getVersionType() == latestType.getVersion())) {
this.setVersionType(resumedMessage.getVersionType());
this.setMessageOnSession(resumedMessage);
Step currentStep = configType.getStepsConfig().getNextStep(resumedMessage.getLastCompletedStep());
while (!ognlValidation(currentStep)) {
currentStep = configType.getStepsConfig().getNextStep(currentStep.getCode());
}
this.setCurrentStepCode(currentStep.getCode());
} else {
// create a new form and left the older AS IS
_logger.debug("webform: updating form {} from version {} to {}", resumedMessage.getId(), resumedMessage.getVersionType(),latestType.getVersion());
// get the last version of the form
latestType = this.getMessageManager().getTypeVersionGui(typeCode);
// update step
StepsConfig stepsConfig = latestType.getStepsConfig();
Step firstStep = stepsConfig.getFirstStep();
this.setCurrentStepCode(firstStep.getCode());
// copy original values into the new
Message updatedMessage = getMessageManager().getMessage(resumedMessage.getId(), latestType);
// update version
updatedMessage.setVersionType(latestType.getVersion());
// update entity
this.getMessageManager().addUpdateMessage(updatedMessage);
// put it on session
this.setMessageOnSession(updatedMessage);
// update version type
this.setVersionType(updatedMessage.getVersionType());
// create GUI
this.getGuiGeneratorManager().checkUserGuis(latestType);
}
}
} catch (Throwable t) {
_logger.error("error in createNew", t);
return FAILURE;
}
return SUCCESS;
}
//
// private Step ognlValidation(NAVIGATE navigate) throws ApsSystemException {
// Message currentMessage = this.getMessage();
// StepsConfig stepsConfig = this.getMessageManager().getStepsConfig(currentMessage.getTypeCode());
// List<Step> steps = stepsConfig.getSteps();
// Iterator<Step> iterator = steps.iterator();
// try {
// Step step = stepsConfig.getStep(this.getCurrentStepCode());
// while (iterator.hasNext() && !ognlValidationHelper(step)) {
// step = iterator.next();
// }
// this.setCurrentStepCode(step.getCode());
// return step;
// } catch (Throwable t) {
// ApsSystemUtils.logThrowable(t, this, "ognlValidation");
// throw new ApsSystemException("ognlValidation", t.getCause());
// }
// }
private Boolean ognlValidation(Step step) throws ApsSystemException {
return this.getMessageManager().validateOgnl(step.getOgnlExpression(), this.getMessage(), this.getCurrentUser().getUsername());
}
/**
* Get the message on hold for the current user
*
* @return
* @throws ApsSystemException
*/
private Message resumeMessage() throws ApsSystemException {
if (isGuest()) {
return null;
}
return this.getMessageManager().resumeMessageByUserAndType(this.getCurrentUser().getUsername(), this.getTypeCode(), new Integer(0));
}
public String submitStep() {
return navigateForm(NAVIGATE.FORWARD);
}
public String previousStep() {
this.getEntityActionHelper().updateEntity(this.getApsEntity(), this.getRequest());
return navigateForm(NAVIGATE.BACK);
}
@Override
public String edit() {
// Operation Not Allowed
return null;
}
public String entryForm() {
try {
Message message = this.getMessage();
if (message == null) {
return "expiredMessage";
}
} catch (Throwable t) {
_logger.error("error in entryForm", t);
return FAILURE;
}
return SUCCESS;
}
@Override
public String save() {
return SUCCESS;
}
public String resume() {
try {
Message currentMessage = this.getMessage();
if (currentMessage != null) {
TypeVersionGuiConfig config = this.getMessageManager().getTypeVersionGui(currentMessage.getTypeCode(), currentMessage.getVersionType());
this.setVersionType(currentMessage.getVersionType());
this.setTypeCode(currentMessage.getTypeCode());
}
} catch (Throwable t) {
_logger.error("error in Error resuming message", t);
throw new RuntimeException("Error resuming message", t);
}
return SUCCESS;
}
public TypeVersionGuiConfig getVersionConfigFromSession() {
return (TypeVersionGuiConfig) this.getRequest().getSession().getAttribute(JpwebformSystemConstants.SESSION_PARAM_NAME_CURRENT_VERSION_CONFIG);
}
public void setVersionConfigOnSession(TypeVersionGuiConfig config) {
this.getRequest().getSession().setAttribute(JpwebformSystemConstants.SESSION_PARAM_NAME_CURRENT_VERSION_CONFIG, config);
}
public Message getMessage() {
if (this._message == null) {
try {
String sessionParamName = this.getSessionParamName();
this._message = (Message) this.getRequest().getSession().getAttribute(sessionParamName);
} catch (Throwable t) {
_logger.error("Error finding message", t);
throw new RuntimeException("Error finding message", t);
}
}
return _message;
}
protected void setMessageOnSession(Message message) {
String sessionParamName = this.getSessionParamName();
if (message == null) {
this.getRequest().getSession().removeAttribute(sessionParamName);
} else {
this.getRequest().getSession().setAttribute(sessionParamName, message);
}
this._message = message;
}
/**
* Returns the name of the session parameter containing the current Message.
*
* @return The name of the session parameter containing the current Message.
*/
protected String getSessionParamName() {
String typeCode = this.getTypeCode();
return JpwebformSystemConstants.SESSION_PARAM_NAME_CURRENT_FORM + typeCode;
}
/**
* Returns the current language from front-end context.
*
* @return The current language.
*/
@Override
public Lang getCurrentLang() {
super.getCurrentLang();
if (null == this._currentLang) {
RequestContext reqCtx = (RequestContext) this.getRequest().getAttribute(RequestContext.REQCTX);
if (null != reqCtx) {
this._currentLang = (Lang) reqCtx.getExtraParam(SystemConstants.EXTRAPAR_CURRENT_LANG);
}
if (null == this._currentLang) {
this._currentLang = this.getLangManager().getDefaultLang();
}
}
return this._currentLang;
}
private String navigateForm(NAVIGATE navigate) {
try {
String typeCode = this.getTypeCode();
TypeVersionGuiConfig config = this.getVersionConfigFromSession();
boolean isPreview = (config != null && config.getVersion() == 0);
if (null == config) {
//MANAGE ERROR
//return FAILURE;
return "voidTypeCode";
}
if (!config.getFormTypeCode().equals(typeCode)) {
//MANAGE ERROR
return FAILURE;
}
this.setVersionType(config.getVersion());
Message message = this.getMessage();
if (!isPreview && (isGuest() && message.isCompleted() || !isGuest())) {
message.setSendDate(new Date());
this.getMessageManager().addUpdateMessage(message);
}
String previsiousStepCode = this.getCurrentStepCode();
StepsConfig stepsConfig = config.getStepsConfig();
Step nextStep = null;
switch (navigate) {
case BACK:
nextStep = stepsConfig.getPreviousStep(previsiousStepCode);
while (!ognlValidation(nextStep)) {
nextStep = stepsConfig.getPreviousStep(nextStep.getCode());
}
if (null != nextStep) {
message.setLastCompletedStep(nextStep.getCode());
}
break;
case FORWARD:
message.setLastCompletedStep(this.getCurrentStepCode());
nextStep = stepsConfig.getNextStep(previsiousStepCode);
while (!ognlValidation(nextStep)) {
nextStep = stepsConfig.getNextStep(nextStep.getCode());
}
break;
}
if (null != nextStep && nextStep.getCode().equals(JpwebformSystemConstants.COMPLETED_STEP_CODE)) {
Step lastStep = stepsConfig.getLastStep();
if (previsiousStepCode.equals(JpwebformSystemConstants.CONFIRM_STEP_CODE)
|| !stepsConfig.isConfirmGui()) {
this.setPreviousStepCode(lastStep.getCode());
this.setCurrentStepCode(JpwebformSystemConstants.COMPLETED_STEP_CODE);
if (!isPreview) {
message.setCompleted(true);
message.setSendDate(new Date());
this.getMessageManager().addUpdateMessage(message);
this.getMessageManager().sendMessage(message);
if (this.isSendMail() && (null != this.getCustomEmail() && !this.getCustomEmail().isEmpty())) {
this.getMessageManager().sendMessage(message, this.getCustomEmail());
}
}
}
}
Step previousStep = stepsConfig.getPreviousStep(this.getCurrentStepCode());
if (null != previousStep) {
while (!ognlValidation(previousStep)) {
previousStep = stepsConfig.getPreviousStep(previousStep.getCode());
}
}
this.setPreviousStepCode((previousStep != null) ? previousStep.getCode() : null);
this.setCurrentStepCode(nextStep.getCode());
if (!isPreview) {
message.activateAttributes();
message.toggleAttribute(nextStep.getCode());
if (isGuest() && message.isCompleted() || !isGuest()) {
this.getMessageManager().addUpdateMessage(message);
}
}
} catch (Throwable t) {
_logger.error("error in submitStep", t);
return FAILURE;
}
return SUCCESS;
}
/**
* Extract the typeCode from the current showlet.
*
* @return The type code extracted from the showlet.
*/
protected String extractTypeCode() {
String typeCode = null;
RequestContext reqCtx = (RequestContext) this.getRequest().getAttribute(RequestContext.REQCTX);
if (reqCtx != null) {
Widget showlet = (Widget) reqCtx.getExtraParam(SystemConstants.EXTRAPAR_CURRENT_WIDGET);
if (showlet != null) {
ApsProperties config = showlet.getConfig();
if (null != config) {
String showletTypeCode = config.getProperty(JpwebformSystemConstants.WIDGET_PARAM_TYPECODE);
if (showletTypeCode != null && showletTypeCode.trim().length() > 0) {
typeCode = showletTypeCode.trim();
}
}
}
}
return typeCode;
}
public String getCurrentTypeCode() {
return this.getTypeCode();
}
public String getTypeCode() {
if (null == this._typeCode) {
this._typeCode = this.extractTypeCode();
}
return _typeCode;
}
public void setTypeCode(String typeCode) {
String showletTypeCode = this.extractTypeCode();
this._typeCode = (null == showletTypeCode) ? typeCode : showletTypeCode;
}
public Integer getVersionType() {
return _versionType;
}
public void setVersionType(Integer versionType) {
this._versionType = versionType;
}
public List<Lang> getLangs() {
return this.getLangManager().getLangs();
}
public String getCurrentStepCode() {
return _currentStepCode;
}
public void setCurrentStepCode(String currentStepCode) {
this._currentStepCode = currentStepCode;
}
public String getPreviousStepCode() {
return _previousStepCode;
}
public void setPreviousStepCode(String previousStepCode) {
this._previousStepCode = previousStepCode;
}
protected IGuiGeneratorManager getGuiGeneratorManager() {
return _guiGeneratorManager;
}
public void setGuiGeneratorManager(IGuiGeneratorManager guiGeneratorManager) {
this._guiGeneratorManager = guiGeneratorManager;
}
protected IFormManager getMessageManager() {
return _messageManager;
}
public void setMessageManager(IFormManager messageManager) {
this._messageManager = messageManager;
}
public IMailManager getMailManager() {
return _mailManager;
}
public void setMailManager(IMailManager mailManager) {
this._mailManager = mailManager;
}
public String getCurrentUserEmail() {
IApsEntity profile = (IApsEntity) this.getCurrentUser().getProfile();
if (profile != null) {
MonoTextAttribute email = (MonoTextAttribute) profile.getAttribute("email");
return email.getText();
}
return "";
}
public void setCurrentUserEmail(String currentUserEmail) {
this._currentUserEmail = currentUserEmail;
}
public String getCustomEmail() {
return _customEmail;
}
public void setCustomEmail(String customEmail) {
this._customEmail = customEmail;
}
public boolean isSendMail() {
return _sendMail;
}
public void setSendMail(boolean sendMail) {
this._sendMail = sendMail;
}
private boolean isGuest() {
return "guest".equals(this.getCurrentUser().getUsername());
}
private boolean _sendMail;
private String _currentUserEmail;
private String _customEmail;
private String _typeCode;
private Integer _versionType;
private Lang _currentLang;
private Message _message;
private String _currentStepCode;
private String _previousStepCode;
private IFormManager _messageManager;
private IGuiGeneratorManager _guiGeneratorManager;
private IMailManager _mailManager;
public enum NAVIGATE {
BACK, FORWARD
}
}