package org.emforge.projectmanager.web.validator;
import java.util.Collection;
import javax.faces.application.FacesMessage;
import javax.faces.component.StateHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import org.apache.commons.lang.StringUtils;
import org.emforge.projectmanager.ProjectService;
import org.emforge.projectmanager.base.MilestoneDO;
import org.emforge.projectmanager.base.ProjectDO;
import org.emforge.projectmanager.web.bean.MilestoneController;
import org.emforge.projectmanager.web.bean.SettingsController;
/**
* Validates inputed name for a project
*
* @author mchirkov
*/
public class NameValidator implements Validator, StateHolder {
public static final char[] INVALID_CHARS = new char[] {'*', '@', '/', '\\'};
public static final int MAX_NAME_LENGTH = 50;
public static final String VALUEREQUIRED_ERROR_MESSAGE = "Error: value is required.";
public static final String INVALIDCHARS_ERROR_MESSAGE = "Error: inputed value contains invalid characters.";
public static final String LENGTH_ERROR_MESSAGE = "Error: the length of inputed value is greater than maximum allowable.";
public static final String PROJECTEXISTS_ERROR_MESSAGE = "Error: project with such name already exists.";
public static final String MILESTONEEXISTS_ERROR_MESSAGE = "Error: milestone with such name already exists.";
public static final String PROJECTDISPLAYNAME_ERROR_MESSAGE = "Error: project display name should be unique.";
public static final String MILESTONEDISPLAYNAME_ERROR_MESSAGE = "Error: milestone display name should be unique in the project.";
public static final String WIKIPROJECTEXISTS_ERROR_MESSAGE = "Error: project with such wiki page already exists.";
public static final String WIKIMILESTONEEXISTS_ERROR_MESSAGE = "Error: milestone with such wiki page already exists.";
public static final String PROJECT_OBJECT_TYPE = "project";
public static final String MILESTONE_OBJECT_TYPE = "milestone";
String m_objectType;
Boolean m_checkDisplayName;
Long m_objectId;
public void setObjectType(String i_objectType) {
m_objectType = i_objectType;
}
public void setObjectId(Long i_objectId) {
m_objectId = i_objectId;
}
public void setCheckDisplayName(Boolean checkDisplayName) {
m_checkDisplayName = checkDisplayName;
}
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (m_checkDisplayName != null && m_checkDisplayName == true) {
validateDisplayName(context, component, value);
} else {
validateName(context, component, value);
}
}
private void validateName(FacesContext context, UIComponent component, Object value) throws ValidatorException {
String val = StringUtils.strip((String)value);
Long objectId = getObjectId(context);
if (StringUtils.isEmpty(val)) {
throw new ValidatorException(
new FacesMessage(VALUEREQUIRED_ERROR_MESSAGE, VALUEREQUIRED_ERROR_MESSAGE)
);
} else if (!StringUtils.containsNone(val, INVALID_CHARS)) {
throw new ValidatorException(
new FacesMessage(INVALIDCHARS_ERROR_MESSAGE, INVALIDCHARS_ERROR_MESSAGE)
);
} else if (val.length() > MAX_NAME_LENGTH) {
throw new ValidatorException(
new FacesMessage(LENGTH_ERROR_MESSAGE, LENGTH_ERROR_MESSAGE)
);
} else if (m_objectType.equals(PROJECT_OBJECT_TYPE)) {
ProjectService projectService = getProjectService(context);
if (projectService != null) {
ProjectDO project = projectService.getProject(val);
if (project != null && (objectId == null ||
project.getId().longValue() != objectId.longValue())) {
throw new ValidatorException(
new FacesMessage(PROJECTEXISTS_ERROR_MESSAGE, PROJECTEXISTS_ERROR_MESSAGE)
);
}
}
} else if (m_objectType.equals(MILESTONE_OBJECT_TYPE)) {
ProjectService projectService = getProjectService(context);
if (projectService != null) {
MilestoneDO milestone = projectService.getMilestone(val);
if (milestone != null && (objectId == null ||
milestone.getId().longValue() != objectId.longValue())) {
throw new ValidatorException(
new FacesMessage(WIKIMILESTONEEXISTS_ERROR_MESSAGE,
WIKIMILESTONEEXISTS_ERROR_MESSAGE)
);
}
}
}
}
private void validateDisplayName(FacesContext context, UIComponent component, Object value) throws ValidatorException {
String val = StringUtils.strip((String)value);
if (StringUtils.isEmpty(val)) {
throw new ValidatorException(
new FacesMessage(VALUEREQUIRED_ERROR_MESSAGE, VALUEREQUIRED_ERROR_MESSAGE)
);
}
Long objectId = getObjectId(context);
if (m_objectType.equals(PROJECT_OBJECT_TYPE)) {
ProjectService projectService = getProjectService(context);
if (projectService != null) {
// get all projects
Collection<ProjectDO> projects = projectService.getAllProjects();
// check all projects
// theoretically we can have several projects with same display name
// but currently we should not allow user to create them via GUI
boolean found = false;
for (ProjectDO project : projects) {
if (val.equals(project.getDisplayName())) {
if (objectId == null) {
// we are creating new project with display name already exist in the system
// error should be generated
throw new ValidatorException(new FacesMessage(PROJECTDISPLAYNAME_ERROR_MESSAGE, PROJECTDISPLAYNAME_ERROR_MESSAGE));
} else {
if (project.getId().equals(m_objectId)) {
// we have edited project in list - it's ok
return;
} else {
found = true;
}
}
}
}
// we found project with same display name - but it was not same project
// error
if (found) {
throw new ValidatorException(new FacesMessage(PROJECTDISPLAYNAME_ERROR_MESSAGE, PROJECTDISPLAYNAME_ERROR_MESSAGE));
}
}
} else if (m_objectType.equals(MILESTONE_OBJECT_TYPE)) {
ProjectService projectService = getProjectService(context);
ProjectDO project = getProjectForEditedMilestone(context);
// get project for edited milestone
if (projectService != null && project != null) {
// we should not allow to create milestone with display name,
// already existed in current project
Collection<MilestoneDO> milestones = projectService.getMilestones(project);
boolean found = false;
for (MilestoneDO milestone : milestones) {
if (val.equals(milestone.getDisplayName())) {
if (objectId == null) {
// we are creating new milestone with display name already exist in the system
// error should be generated
throw new ValidatorException(new FacesMessage(MILESTONEDISPLAYNAME_ERROR_MESSAGE, MILESTONEDISPLAYNAME_ERROR_MESSAGE));
} else {
if (milestone.getId().equals(m_objectId)) {
// we have edited milestone in list - it's ok
return;
} else {
found = true;
}
}
}
}
if (found) {
throw new ValidatorException(new FacesMessage(MILESTONEDISPLAYNAME_ERROR_MESSAGE, MILESTONEDISPLAYNAME_ERROR_MESSAGE));
}
}
}
}
private ProjectService getProjectService(FacesContext context) {
return (ProjectService) context.getApplication().getVariableResolver().resolveVariable(context, "projectService");
}
/** Sometimes objectId is not specified - but we should get it from SettingsController (for project)
* or MilestoneController (for milestone)
* @param context
* @return
*/
private Long getObjectId(FacesContext context) {
if (m_objectId != null && m_objectId.longValue() != 0) {
return m_objectId;
} else {
if (m_objectType.equals(PROJECT_OBJECT_TYPE)) {
// Object might have been created, so try to get its id from controller
SettingsController settingsController = (SettingsController) context.getApplication(). getVariableResolver().resolveVariable(context, "projectSettingsController");
if (settingsController != null) {
return settingsController.getProjectId();
}
} else if (m_objectType.equals(MILESTONE_OBJECT_TYPE)) {
MilestoneController milestoneController = (MilestoneController) context.getApplication().getVariableResolver().resolveVariable(context, "milestoneController");
if (milestoneController != null) {
MilestoneDO milestone = milestoneController.getMilestone();
if (milestone != null) {
return milestone.getId();
}
}
}
}
return null;
}
private ProjectDO getProjectForEditedMilestone(FacesContext context) {
ProjectService projectService = getProjectService(context);
if (m_objectId != null && m_objectId != 0) {
MilestoneDO milestone = projectService.getMilestone(m_objectId);
return milestone.getProject();
} else {
MilestoneController milestoneController = (MilestoneController) context.getApplication().getVariableResolver().resolveVariable(context, "milestoneController");
if (milestoneController != null) {
return milestoneController.getMilestone().getProject();
}
}
return null;
}
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
m_objectType = (String) values[0];
m_objectId = (Long) values[1];
m_checkDisplayName = (Boolean)values[2];
}
public Object saveState(FacesContext context) {
Object values[] = new Object[3];
values[0] = m_objectType;
values[1] = m_objectId;
values[2] = m_checkDisplayName;
return (values);
}
private boolean isTransient;
public boolean isTransient() {
return isTransient;
}
public void setTransient(boolean isTransient) {
this.isTransient = isTransient;
}
}
|