/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package edu.harvard.iq.dataverse;
import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
import edu.harvard.iq.dataverse.engine.command.impl.CreateHarvestingClientCommand;
import edu.harvard.iq.dataverse.engine.command.impl.UpdateHarvestingClientCommand;
import edu.harvard.iq.dataverse.harvest.client.HarvestingClient;
import edu.harvard.iq.dataverse.harvest.client.HarvestingClientServiceBean;
import edu.harvard.iq.dataverse.harvest.server.OAIRecord;
import edu.harvard.iq.dataverse.harvest.server.OAIRecordServiceBean;
import edu.harvard.iq.dataverse.harvest.server.OAISet;
import edu.harvard.iq.dataverse.harvest.server.OAISetServiceBean;
import edu.harvard.iq.dataverse.harvest.server.OaiSetException;
import edu.harvard.iq.dataverse.util.JsfHelper;
import static edu.harvard.iq.dataverse.util.JsfHelper.JH;
import edu.harvard.iq.dataverse.util.SystemConfig;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang.StringUtils;
/**
*
* @author Leonid Andreev
*/
@ViewScoped
@Named
public class HarvestingSetsPage implements java.io.Serializable {
private static final Logger logger = Logger.getLogger(HarvestingSetsPage.class.getCanonicalName());
@Inject
DataverseSession session;
@EJB
AuthenticationServiceBean authSvc;
@EJB
DataverseServiceBean dataverseService;
@EJB
OAISetServiceBean oaiSetService;
@EJB
OAIRecordServiceBean oaiRecordService;
@EJB
EjbDataverseEngine engineService;
@EJB
SystemConfig systemConfig;
@Inject
DataverseRequestServiceBean dvRequestService;
@Inject
NavigationWrapper navigationWrapper;
private List<OAISet> configuredHarvestingSets;
private OAISet selectedSet;
private boolean setSpecValidated = false;
private boolean setQueryValidated = false;
private int setQueryResult = -1;
public enum PageMode {
VIEW, CREATE, EDIT
}
private PageMode pageMode = PageMode.VIEW;
private int oaiServerStatusRadio;
private static final int oaiServerStatusRadioDisabled = 0;
private static final int oaiServerStatusRadioEnabled = 1;
private UIInput newSetSpecInputField;
private UIInput newSetQueryInputField;
private String newSetSpec = "";
private String newSetDescription = "";
private String newSetQuery = "";
public String getNewSetSpec() {
return newSetSpec;
}
public void setNewSetSpec(String newSetSpec) {
this.newSetSpec = newSetSpec;
}
public String getNewSetDescription() {
return newSetDescription;
}
public void setNewSetDescription(String newSetDescription) {
this.newSetDescription = newSetDescription;
}
public String getNewSetQuery() {
return newSetQuery;
}
public void setNewSetQuery(String newSetQuery) {
this.newSetQuery = newSetQuery;
}
public int getOaiServerStatusRadio() {
return this.oaiServerStatusRadio;
}
public void setOaiServerStatusRadio(int oaiServerStatusRadio) {
this.oaiServerStatusRadio = oaiServerStatusRadio;
}
public String init() {
if (!isSessionUserAuthenticated()) {
return "/loginpage.xhtml" + navigationWrapper.getRedirectPage();
} else if (!isSuperUser()) {
return navigationWrapper.notAuthorized();
}
configuredHarvestingSets = oaiSetService.findAll();
pageMode = PageMode.VIEW;
if (isHarvestingServerEnabled()) {
oaiServerStatusRadio = oaiServerStatusRadioEnabled;
} else {
oaiServerStatusRadio = oaiServerStatusRadioDisabled;
}
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, JH.localize("harvestserver.title"), JH.localize("harvestserver.toptip")));
return null;
}
public List<OAISet> getConfiguredOAISets() {
return configuredHarvestingSets;
}
public void setConfiguredOAISets(List<OAISet> oaiSets) {
configuredHarvestingSets = oaiSets;
}
public boolean isHarvestingServerEnabled() {
return systemConfig.isOAIServerEnabled();
}
public void toggleHarvestingServerStatus() {
if (isHarvestingServerEnabled()) {
systemConfig.disableOAIServer();
} else {
systemConfig.enableOAIServer();
JsfHelper.addSuccessMessage(JH.localize("harvestserver.service.enable.success"));
}
}
public UIInput getNewSetSpecInputField() {
return newSetSpecInputField;
}
public void setNewSetSpecInputField(UIInput newSetSpecInputField) {
this.newSetSpecInputField = newSetSpecInputField;
}
public UIInput getNewSetQueryInputField() {
return newSetQueryInputField;
}
public void setNewSetQueryInputField(UIInput newSetQueryInputField) {
this.newSetQueryInputField = newSetQueryInputField;
}
public void disableHarvestingServer() {
systemConfig.disableOAIServer();
}
public void setSelectedSet(OAISet oaiSet) {
selectedSet = oaiSet;
}
public OAISet getSelectedSet() {
return selectedSet;
}
// init method when the user clicks 'add new set':
public void initNewSet(ActionEvent ae) {
this.newSetSpec = "";
this.newSetDescription = "";
this.newSetQuery = "";
this.pageMode = PageMode.CREATE;
this.setSpecValidated = false;
this.setQueryValidated = false;
this.setQueryResult = -1;
}
// init method when the user clicks 'edit existing set':
public void editSet(OAISet oaiSet) {
this.newSetSpec = oaiSet.getSpec();
this.newSetDescription = oaiSet.getDescription();
this.newSetQuery = oaiSet.getDefinition();
this.pageMode = PageMode.EDIT;
this.setSpecValidated = false;
this.setQueryValidated = false;
this.setQueryResult = -1;
setSelectedSet(oaiSet);
}
public void createSet(ActionEvent ae) {
OAISet newOaiSet = new OAISet();
newOaiSet.setSpec(getNewSetSpec());
newOaiSet.setName(getNewSetSpec());
newOaiSet.setDescription(getNewSetDescription());
newOaiSet.setDefinition(getNewSetQuery());
boolean success = false;
try {
oaiSetService.save(newOaiSet);
configuredHarvestingSets = oaiSetService.findAll();
String successMessage = JH.localize("harvestserver.newSetDialog.success");
successMessage = successMessage.replace("{0}", newOaiSet.getSpec());
JsfHelper.addSuccessMessage(successMessage);
success = true;
} catch (Exception ex) {
JH.addMessage(FacesMessage.SEVERITY_FATAL, "Failed to create OAI set");
logger.log(Level.SEVERE, "Failed to create OAI set" + ex.getMessage(), ex);
}
if (success) {
OAISet savedSet = oaiSetService.findBySpec(getNewSetSpec());
if (savedSet != null) {
runSetExport(savedSet);
configuredHarvestingSets = oaiSetService.findAll();
}
}
setPageMode(HarvestingSetsPage.PageMode.VIEW);
}
// this saves an existing set that the user has edited:
public void saveSet(ActionEvent ae) {
OAISet oaiSet = getSelectedSet();
if (oaiSet == null) {
// TODO:
// tell the user somehow that the set cannot be saved, and advise
// them to save the settings they have entered.
}
// Note that the nickname is not editable:
oaiSet.setDefinition(getNewSetQuery());
oaiSet.setDescription(getNewSetDescription());
// will try to save it now:
boolean success = false;
try {
oaiSetService.save(oaiSet);
configuredHarvestingSets = oaiSetService.findAll();
JsfHelper.addSuccessMessage("Succesfully updated OAI set "" + oaiSet.getSpec() + "".");
success = true;
} catch (Exception ex) {
JH.addMessage(FacesMessage.SEVERITY_FATAL, "Failed to update OAI set.");
logger.log(Level.SEVERE, "Failed to update OAI set." + ex.getMessage(), ex);
}
if (success) {
OAISet createdSet = oaiSetService.findBySpec(getNewSetSpec());
if (createdSet != null) {
runSetExport(createdSet);
configuredHarvestingSets = oaiSetService.findAll();
}
}
setPageMode(HarvestingSetsPage.PageMode.VIEW);
}
public void deleteSet() {
if (selectedSet != null) {
logger.info("proceeding to delete harvesting set "+ selectedSet.getSpec());
try {
oaiSetService.setDeleteInProgress(selectedSet.getId());
oaiSetService.remove(selectedSet.getId());
selectedSet = null;
configuredHarvestingSets = oaiSetService.findAll();
JsfHelper.addInfoMessage(JH.localize("harvestserver.tab.header.action.delete.infomessage"));
} catch (Exception ex) {
String failMessage = "Failed to delete harvesting set; unknown exception: "+ex.getMessage();
JH.addMessage(FacesMessage.SEVERITY_FATAL, failMessage);
}
} else {
logger.warning("Delete called, with a null selected harvesting set!");
}
}
public boolean isSetSpecValidated() {
return this.setSpecValidated;
}
public void setSetSpecValidated(boolean validated) {
this.setSpecValidated = validated;
}
public boolean isSetQueryValidated() {
return this.setQueryValidated;
}
public void setSetQueryValidated(boolean validated) {
this.setQueryValidated = validated;
}
public int getSetQueryResult() {
return this.setQueryResult;
}
public void setSetQueryResult(int setQueryResult) {
this.setQueryResult = setQueryResult;
}
public PageMode getPageMode() {
return this.pageMode;
}
public void setPageMode(PageMode pageMode) {
this.pageMode = pageMode;
}
public boolean isCreateMode() {
return PageMode.CREATE == this.pageMode;
}
public boolean isEditMode() {
return PageMode.EDIT == this.pageMode;
}
public boolean isViewMode() {
return PageMode.VIEW == this.pageMode;
}
public boolean isSessionUserAuthenticated() {
if (session == null) {
return false;
}
if (session.getUser() == null) {
return false;
}
if (session.getUser().isAuthenticated()) {
return true;
}
return false;
}
public int getSetInfoNumOfDatasets(OAISet oaiSet) {
String query = oaiSet.getDefinition();
try {
int num = oaiSetService.validateDefinitionQuery(query);
if (num > -1) {
return num;
}
} catch (OaiSetException ose) {
// do notghin - will return zero.
}
return 0;
}
public int getSetInfoNumOfExported(OAISet oaiSet) {
List<OAIRecord> records = oaiRecordService.findActiveOaiRecordsBySetName(oaiSet.getSpec());
if (records == null || records.isEmpty()) {
return 0;
}
return records.size();
}
public int getSetInfoNumOfDeleted(OAISet oaiSet) {
List<OAIRecord> records = oaiRecordService.findDeletedOaiRecordsBySetName(oaiSet.getSpec());
if (records == null || records.isEmpty()) {
return 0;
}
return records.size();
}
public void validateSetQuery() {
int datasetsFound = 0;
try {
datasetsFound = oaiSetService.validateDefinitionQuery(getNewSetQuery());
} catch (OaiSetException ose) {
FacesContext.getCurrentInstance().addMessage(getNewSetQueryInputField().getClientId(),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", "Search failed for the query provided. Message from the Dataverse search server: "+ose.getMessage()));
setSetQueryValidated(false);
return;
}
setSetQueryValidated(true);
setSetQueryResult(datasetsFound);
}
public void backToQuery() {
setSetQueryValidated(false);
}
/*
version of validateSetSpec() that's not component-driven (must be called explicitly
with action="#{harvestingSetsPage.validateSetSpec}")
public void validateSetSpec() {
if ( !StringUtils.isEmpty(getNewSetSpec()) ) {
if (! Pattern.matches("^[a-zA-Z0-9\\_\\-]+$", getNewSetSpec()) ) {
//input.setValid(false);
FacesContext.getCurrentInstance().addMessage(getNewSetSpecInputField().getClientId(),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", JH.localize("harvestserver.newSetDialog.setspec.invalid")));
setSetSpecValidated(false);
return;
// If it passes the regex test, check
} else if ( oaiSetService.findBySpec(getNewSetSpec()) != null ) {
//input.setValid(false);
FacesContext.getCurrentInstance().addMessage(getNewSetSpecInputField().getClientId(),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", JH.localize("harvestserver.newSetDialog.setspec.alreadyused")));
setSetSpecValidated(false);
return;
}
setSetSpecValidated(true);
return;
}
// Nickname field is empty:
FacesContext.getCurrentInstance().addMessage(getNewSetSpecInputField().getClientId(),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", JH.localize("harvestserver.newSetDialog.setspec.required")));
setSetSpecValidated(false);
return;
}*/
public void validateSetSpec(FacesContext context, UIComponent toValidate, Object rawValue) {
String value = (String) rawValue;
UIInput input = (UIInput) toValidate;
input.setValid(true); // Optimistic approach
if (context.getExternalContext().getRequestParameterMap().get("DO_VALIDATION") != null) {
if (!StringUtils.isEmpty(value)) {
if (!Pattern.matches("^[a-zA-Z0-9\\_\\-]+$", value)) {
input.setValid(false);
context.addMessage(toValidate.getClientId(),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", JH.localize("harvestserver.newSetDialog.setspec.invalid")));
return;
// If it passes the regex test, check
} else if (oaiSetService.findBySpec(value) != null) {
input.setValid(false);
context.addMessage(toValidate.getClientId(),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", JH.localize("harvestserver.newSetDialog.setspec.alreadyused")));
return;
}
// set spec looks legit!
return;
}
// the field can't be left empty either:
input.setValid(false);
context.addMessage(toValidate.getClientId(),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", JH.localize("harvestserver.newSetDialog.setspec.required")));
}
// no validation requested - so we're cool!
}
// this will re-export the set in the background, asynchronously:
public void startSetExport(OAISet oaiSet) {
try {
runSetExport(oaiSet);
} catch (Exception ex) {
String failMessage = "Sorry, could not start re-export on selected OAI set (unknown server error).";
JH.addMessage(FacesMessage.SEVERITY_FATAL, failMessage);
return;
}
String successMessage = JH.localize("harvestserver.actions.runreexport.success");
successMessage = successMessage.replace("{0}", oaiSet.getSpec());
JsfHelper.addSuccessMessage(successMessage);
configuredHarvestingSets = oaiSetService.findAll();
}
public void runSetExport(OAISet oaiSet) {
oaiSetService.setUpdateInProgress(oaiSet.getId());
oaiSetService.exportOaiSetAsync(oaiSet);
}
public boolean isSuperUser() {
return session.getUser().isSuperuser();
}
}