/*********************************************************************************
* The contents of this file are subject to the Common Public Attribution
* License Version 1.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.openemm.org/cpal1.html. The License is based on the Mozilla
* Public License Version 1.1 but Sections 14 and 15 have been added to cover
* use of software over a computer network and provide for limited attribution
* for the Original Developer. In addition, Exhibit A has been modified to be
* consistent with Exhibit B.
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is OpenEMM.
* The Original Developer is the Initial Developer.
* The Initial Developer of the Original Code is AGNITAS AG. All portions of
* the code written by AGNITAS AG are Copyright (c) 2009 AGNITAS AG. All Rights
* Reserved.
*
* Contributor(s): AGNITAS AG.
********************************************************************************/
package org.agnitas.web;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.agnitas.beans.Admin;
import org.agnitas.beans.ImportProfile;
import org.agnitas.beans.impl.ImportProfileImpl;
import org.agnitas.dao.AdminDao;
import org.agnitas.dao.ImportProfileDao;
import org.agnitas.util.AgnUtils;
import org.agnitas.util.ImportUtils;
import org.agnitas.util.importvalues.ImportMode;
import org.agnitas.web.forms.ImportProfileForm;
import org.agnitas.web.forms.StrutsFormBase;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
/**
* Action that handles import profile actions: view, edit, remove, list,
* manage gender mappings.
*
* @author Vyacheslav Stepanov
*/
public class ImportProfileAction extends StrutsActionBase {
private static final transient Logger logger = Logger.getLogger(ImportProfileAction.class);
public static final int ACTION_NEW_GENDER = ACTION_LAST + 1;
public static final int ACTION_REMOVE_GENDER = ACTION_LAST + 2;
public static final int ACTION_SET_DEFAULT = ACTION_LAST + 3;
public static final String IMPORT_PROFILE_ERRORS_KEY = "import-profile-errors";
public static final String IMPORT_PROFILE_ID_KEY = "import-profile-id";
/**
* Process the specified HTTP request, and create the corresponding HTTP
* response (or forward to another web component that will create it).
* Return an <code>ActionForward</code> instance describing where and how
* control should be forwarded, or <code>null</code> if the response has
* already been completed.
* <br>
* ACTION_LIST: loads list of profile fields and default profile field into request and forwards to profile
* field list page.
* <br><br>
* ACTION_NEW_GENDER: saves gender mappings converting that from sequence if new gender is not empty and
* forwards to profile field view page.
* <br><br>
* ACTION_REMOVE_GENDER: removes gender mapping from profile field and forwards to profile field view page.
* <br><br>
* ACTION_VIEW: loads data of chosen profile field into form and forwards to profile field view page.
* <br><br>
* ACTION_SAVE: checks, if profile field with entered name already exists. Saves profile field data or creates
* a new one and forwards to profile field view page.
* <br><br>
* ACTION_NEW: creates empty instance of profile field and forwards to profile field view page.<br>
* Supported modes for import: <br>
* ImportMode.ADD (adds only new recipients)
* requires "import.mode.add" permission<br>
* ImportMode.ADD_AND_UPDATE (adds new recipients and update existing recipients)
* requires "import.mode.add_update" permission<br>
* ImportMode.UPDATE (only updates existing recipients)
* requires "import.mode.only_update" permission<br>
* ImportMode.MARK_OPT_OUT (marks recipients as Opt Out)
* requires "import.mode.unsubscribe" permission<br>
* ImportMode.MARK_BOUNCED (marks recipients as Bounced)
* requires "import.mode.bounce" permission<br>
* ImportMode.TO_BLACKLIST (adds recipients to blacklist)
* requires "import.mode.blacklist" permission
* <br><br>
* ACTION_SET_DEFAULT: saves the default profile id for admin in database and in session.
* Forwards to profile field list page.
* <br><br>
* ACTION_CONFIRM_DELETE: loads profile field data and forwards to jsp with question to confirm deletion.
* <br><br>
* ACITON_DELETE: deletes profile field and forwards to profile field list page.
* <br><br>
* @param mapping The ActionMapping used to select this instance
* @param form The optional ActionForm bean for this request (if any)
* @param request The HTTP request we are processing<br>
* If the request parameter "addGender" is set - changes action to ACTION_REMOVE_GENDER.<br>
* If the request parameter "removeGender" is set - changes action to ACTION_REMOVE_GENDER.<br>
* If the request parameter "setDefault" is set - changes action to ACTION_SET_DEFAULT.<br>
* @param res The HTTP response we are creating
* @throws java.io.IOException if an input/output error occurs
* @throws javax.servlet.ServletException if a servlet exception occurs
* @return destination specified in struts-config.xml to forward to next jsp
*/
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse res)
throws IOException, ServletException {
// Validate the request parameters specified by the user
ImportProfileForm aForm;
ActionMessages errors = new ActionMessages();
ActionMessages messages = new ActionMessages();
ActionForward destination = null;
if (!AgnUtils.isUserLoggedIn(request)) {
return mapping.findForward("logon");
}
if (form != null) {
aForm = (ImportProfileForm) form;
} else {
aForm = new ImportProfileForm();
}
if (logger.isInfoEnabled()) logger.info("Action: " + aForm.getAction());
if (request.getSession().getAttribute(IMPORT_PROFILE_ID_KEY) != null) {
errors = (ActionMessages) request.getSession().getAttribute(IMPORT_PROFILE_ERRORS_KEY);
int profileId = (Integer) request.getSession().getAttribute(IMPORT_PROFILE_ID_KEY);
aForm.setProfileId(profileId);
aForm.setAction(ACTION_VIEW);
request.getSession().removeAttribute(IMPORT_PROFILE_ERRORS_KEY);
request.getSession().removeAttribute(IMPORT_PROFILE_ID_KEY);
}
if (AgnUtils.parameterNotEmpty(request, "addGender")) {
aForm.setAction(ACTION_NEW_GENDER);
}
if (ImportUtils.hasNoEmptyParameterStartsWith(request, "removeGender")) {
aForm.setAction(ACTION_REMOVE_GENDER);
}
if (AgnUtils.parameterNotEmpty(request, "setDefault")) {
aForm.setAction(ACTION_SET_DEFAULT);
}
try {
switch (aForm.getAction()) {
case ImportProfileAction.ACTION_LIST:
destination = mapping.findForward("list");
aForm.reset(mapping, request);
aForm.setAction(ImportProfileAction.ACTION_LIST);
break;
case ImportProfileAction.ACTION_VIEW:
aForm.reset(mapping, request);
loadImportProfile(aForm);
setAvailableImportModes(aForm, request);
aForm.setAction(ImportProfileAction.ACTION_SAVE);
destination = mapping.findForward("view");
break;
case ImportProfileAction.ACTION_NEW_GENDER:
if (StringUtils.isEmpty(aForm.getAddedGender())) {
errors.add("newGender", new ActionMessage("error.import.gender.empty"));
} else {
boolean success = aForm.getProfile().addGenderMappingSequence(aForm.getAddedGender(), aForm.getAddedGenderInt());
if (success) {
aForm.setAddedGender("");
aForm.setAddedGenderInt(0);
} else {
errors.add("newGender", new ActionMessage("error.import.gender.number.duplicate"));
}
}
aForm.setAction(ImportProfileAction.ACTION_SAVE);
destination = mapping.findForward("view");
break;
case ImportProfileAction.ACTION_REMOVE_GENDER:
String gender = ImportUtils.getNotEmptyValueFromParameter(request, "removeGender_");
int genderValue = 0;
StringTokenizer stringTokenizerNewGender = new StringTokenizer(gender, ",");
while (stringTokenizerNewGender.hasMoreTokens()) {
String genderToken = stringTokenizerNewGender.nextToken().trim();
genderValue = aForm.getProfile().getGenderMapping().get(genderToken);
aForm.getProfile().getGenderMapping().remove(genderToken);
}
aForm.setAddedGender(gender);
aForm.setAddedGenderInt(genderValue);
aForm.setAction(ImportProfileAction.ACTION_SAVE);
destination = mapping.findForward("view");
break;
case ImportProfileAction.ACTION_SAVE:
if (!checkErrorsOnSave(aForm, request, errors)) {
saveImportProfile(aForm);
messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("default.changes_saved"));
}
aForm.setAction(ImportProfileAction.ACTION_SAVE);
destination = mapping.findForward("view");
break;
case ImportProfileAction.ACTION_NEW:
aForm.reset(mapping, request);
aForm.setAction(ImportProfileAction.ACTION_SAVE);
createEmptyProfile(aForm, request);
setAvailableImportModes(aForm, request);
destination = mapping.findForward("view");
break;
case ImportProfileAction.ACTION_SET_DEFAULT:
setDefaultProfile(aForm, request);
aForm.setAction(ImportProfileAction.ACTION_LIST);
destination = mapping.findForward("list");
messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("default.changes_saved"));
break;
case ImportProfileAction.ACTION_CONFIRM_DELETE:
loadImportProfile(aForm);
aForm.setAction(ImportProfileAction.ACTION_DELETE);
destination = mapping.findForward("delete");
break;
case ImportProfileAction.ACTION_DELETE:
if (request.getParameter("kill") != null) {
removeProfile(aForm);
aForm.setAction(ImportProfileAction.ACTION_LIST);
messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("default.changes_saved"));
}
destination = mapping.findForward("list");
break;
default:
aForm.setAction(ImportProfileAction.ACTION_LIST);
destination = mapping.findForward("list");
}
} catch (Exception e) {
logger.error("execute: " + e + "\n" + AgnUtils.getStackTrace(e));
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.exception"));
}
if (destination != null && "list".equals(destination.getName())) {
try {
// if we will go to list page we need to load profiles list
// and load the default profile for current admin to show
// that on list-page
setNumberOfRows(request, (StrutsFormBase) form);
request.setAttribute("profileList", getProfileList(request));
aForm.setDefaultProfileId(AgnUtils.getAdmin(request).getDefaultImportProfileID());
} catch (Exception e) {
logger.error("getCampaignList: " + e + "\n" + AgnUtils.getStackTrace(e));
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.exception"));
}
}
// Report any errors we have discovered back to the original form
if (!errors.isEmpty()) {
saveErrors(request, errors);
}
if (!messages.isEmpty()) {
saveMessages(request, messages);
}
return destination;
}
protected boolean checkErrorsOnSave(ImportProfileForm aForm, HttpServletRequest request, ActionMessages errors) throws InstantiationException, IllegalAccessException {
boolean hasErrors = false;
if (profileNameIsDuplicate(aForm, request)) {
errors.add("shortname", new ActionMessage("error.import.duplicate_profile_name"));
hasErrors = true;
}
return hasErrors;
}
/**
* Loads the list of allowed import modes for current user.
*
* @param aForm form
* @param request request
*/
private void setAvailableImportModes(ImportProfileForm aForm, HttpServletRequest request) {
List<ImportMode> allowedModes = new ArrayList<ImportMode>();
for (ImportMode mode : ImportMode.values()) {
if (allowed(mode.getPublicValue().substring("UserRight.Import.".length()), request)) {
allowedModes.add(mode);
}
}
aForm.setImportModes(allowedModes.toArray(new ImportMode[0]));
}
/**
* Method checks if there is already a profile with a name user entered creating new profile
*
* @param aForm form
* @param request request
* @return true if the profile with such name alreay exists, false if not
* @throws IllegalAccessException
* @throws InstantiationException
*/
private boolean profileNameIsDuplicate(ImportProfileForm aForm, HttpServletRequest request)
throws IllegalAccessException, InstantiationException {
String profileName = aForm.getProfile().getName();
int profileId = aForm.getProfileId();
List<ImportProfile> importProfileList = getProfileList(request);
for (ImportProfile importProfile : importProfileList) {
if (importProfile.getName().equals(profileName) && importProfile.getId() != profileId) {
return true;
}
}
return false;
}
/**
* Saves the default profile id for admin that is set on overview-page
*
* @param aForm a form
* @param request request
*/
private void setDefaultProfile(ImportProfileForm aForm, HttpServletRequest request) {
int defaultProfileId = aForm.getDefaultProfileId();
Admin admin = AgnUtils.getAdmin(request);
admin.setDefaultImportProfileID(defaultProfileId);
AdminDao adminDao = (AdminDao) getWebApplicationContext().getBean("AdminDao");
Admin adminFromDao = adminDao.getAdmin(admin.getAdminID(), admin.getCompanyID());
adminFromDao.setDefaultImportProfileID(defaultProfileId);
adminDao.save(adminFromDao);
}
/**
* Creates empty profile for displaying on view-page when user wants to
* create new import profile
*
* @param aForm a form
* @param request request
*/
private void createEmptyProfile(ImportProfileForm aForm, HttpServletRequest request) {
ImportProfileImpl newProfile = new ImportProfileImpl();
newProfile.setAdminId(AgnUtils.getAdmin(request).getAdminID());
newProfile.setCompanyId(AgnUtils.getCompanyID(request));
newProfile.setKeyColumn("email");
newProfile.setCheckForDuplicates(1);
newProfile.setDefaultMailType(1);
aForm.setProfile(newProfile);
aForm.setProfileId(0);
}
/**
* Removes profile from system with all its data using Dao
*
* @param aForm a form
*/
public void removeProfile(ImportProfileForm aForm) {
ImportProfileDao profileDao = (ImportProfileDao) getWebApplicationContext().getBean("ImportProfileDao");
profileDao.deleteImportProfileById(aForm.getProfileId());
}
/**
* @param request request
* @return list of import profiles for overview page with current company id
*/
private List<ImportProfile> getProfileList(HttpServletRequest request) throws InstantiationException, IllegalAccessException {
ImportProfileDao profileDao = (ImportProfileDao) getWebApplicationContext().getBean("ImportProfileDao");
return profileDao.getImportProfilesByCompanyId(AgnUtils.getCompanyID(request));
}
/**
* Saves import profile (or creats new if its' "New import profile" page)
*
* @param aForm a form
*/
private void saveImportProfile(ImportProfileForm aForm) {
if (aForm.getProfile().getKeyColumn() != null) {
aForm.getProfile().setKeyColumn(aForm.getProfile().getKeyColumn().toLowerCase());
}
ImportProfileDao profileDao = (ImportProfileDao) getWebApplicationContext().getBean("ImportProfileDao");
if (aForm.getProfileId() != 0) {
profileDao.updateImportProfile(aForm.getProfile());
} else {
profileDao.insertImportProfile(aForm.getProfile());
aForm.setProfileId(aForm.getProfile().getId());
}
}
/**
* Loads import profile to show it on profile view-page
*
* @param aForm a form
*/
private void loadImportProfile(ImportProfileForm aForm) {
ImportProfileDao profileDao = (ImportProfileDao) getWebApplicationContext().getBean("ImportProfileDao");
aForm.setProfile(profileDao.getImportProfileById(aForm.getProfileId()));
}
}