package no.met.metadataeditor.view; import java.io.IOException; import java.io.Serializable; import java.io.StringReader; import java.util.HashMap; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.validator.ValidatorException; import javax.servlet.http.HttpServletRequest; import no.met.metadataeditor.EditorException; import no.met.metadataeditor.EditorUtils; import no.met.metadataeditor.dataTypes.EditorTemplate; import no.met.metadataeditor.dataTypes.EditorVariableContent; import no.met.metadataeditor.datastore.DataStore; import no.met.metadataeditor.datastore.DataStoreFactory; import no.met.metadataeditor.datastore.SupportedFormat; import org.jdom2.Document; import org.jdom2.JDOMException; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @ManagedBean @ViewScoped public class NewRecordBean implements Serializable { private static final Logger logger = Logger.getLogger(NewRecordBean.class.getName()); // automatically set based on the query parameters private String project; // the identifier for a new record. Used when the user clicks "New" private String newRecordIdentifier; // the format for a new record. Used when the user clicks "New" private SupportedFormat newRecordFormat; private static final long serialVersionUID = 6284081275030111665L; /** * Validate that the record identifier is has not been used within a project. * @param context Current context * @param component The originating component * @param value The new identifier value * @throws ValidatorException Throw if the record identifier in value is already in use */ public void validateRecordIdentifier(FacesContext context, UIComponent component, Object value) throws ValidatorException { String identifier = (String) value; String validIdentifier = "[\\w!\"#$%&'()*+,-\\.:;<=>?@{\\|}]+"; if( !identifier.matches(validIdentifier)){ FacesMessage message = new FacesMessage("Record identifier is not valid.", "Record identifier contains invalid characters. Please restrict to normal english letter, number and punctiation characters."); message.setSeverity(FacesMessage.SEVERITY_FATAL); throw new ValidatorException(message); } DataStore datastore = DataStoreFactory.getInstance(project); if( datastore.metadataExists(identifier)){ FacesMessage message = new FacesMessage("Record identifier already in use.", "The record identifier is already in use and cannot be reused for a new record."); message.setSeverity(FacesMessage.SEVERITY_FATAL); throw new ValidatorException(message); } } public List<SupportedFormat> getSupportedFormats() { DataStore datastore = DataStoreFactory.getInstance(project); return datastore.getSupportedFormats(); } public String newRecord() { UserBean user = getUser(); if( user.isValidated() ){ DataStore datastore = DataStoreFactory.getInstance(project); String templateXML = datastore.readTemplate(newRecordFormat); try { EditorTemplate template = new EditorTemplate(new InputSource(new StringReader(templateXML))); Document emptyRecord = template.writeContent(new HashMap<String, List<EditorVariableContent>>()); datastore.writeMetadata(newRecordIdentifier, EditorUtils.docToString(emptyRecord), user.getUsername(), user.getPassword()); } catch (SAXException e) { logger.log(Level.SEVERE, "Failed to parse template", e); throw new EditorException("Failed to parse template", e, EditorException.TEMPLATE_PARSE_ERROR); } catch (IOException e) { logger.log(Level.SEVERE, "Failed to read template", e); throw new EditorException("Failed to read template", e, EditorException.IO_ERROR); } catch (JDOMException e) { logger.log(Level.SEVERE, "Failed to write empty template", e); throw new EditorException("Failed to write template", e, EditorException.IO_ERROR); } return "editor.xhtml?project=" + project + "&record=" + newRecordIdentifier + "&faces-redirect=true"; } else { FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Login required before creating record.", "Login required before creating record"); FacesContext.getCurrentInstance().addMessage(null, msg); return null; } } public String getNewRecordIdentifier() { return newRecordIdentifier; } public void setNewRecordIdentifier(String newRecordIdentifier) { this.newRecordIdentifier = newRecordIdentifier; } public SupportedFormat getNewRecordFormat() { return newRecordFormat; } public void setNewRecordFormat(SupportedFormat newRecordFormat) { this.newRecordFormat = newRecordFormat; } public String getProject() { return project; } public void setProject(String project) { this.project = project; } /** * @return The UserBean object for the current user. */ private UserBean getUser(){ // IMPLEMENTATION NOTE: This was first implemented as a @ManagedProperty, but that did not work // for unknown reasons. It seemed like the UserBean object changed between request even if should // stay the same. So this workaround was added instead. HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest(); return (UserBean) request.getSession().getAttribute("userBean"); } }