public Registration() {
super();
status = RegistrationStatus.values()[(int) (Math.random() * RegistrationStatus.values().length)];
- specificIdentifier = Integer.toString(idAutoincrement++);
+ setId(idAutoincrement++);
+ specificIdentifier = Integer.toString(getId());
identifier = "http://pyhcobank.org/" + specificIdentifier;
registrationDate = DateTime.now();
}
*/
package eu.etaxonomy.cdm.mock;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.UUID;
-import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import eu.etaxonomy.cdm.model.common.CdmBase;
import eu.etaxonomy.cdm.model.name.Rank;
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
+import eu.etaxonomy.cdm.vaadin.model.registration.RegistrationWorkingSet;
import eu.etaxonomy.cdm.vaadin.presenter.registration.RegistrationDTO;
import eu.etaxonomy.cdm.vaadin.presenter.registration.RegistrationValidationException;
private CdmRepository repo;
private Map<UUID, Registration> registrationsByUUID = new HashMap<>();
- private Map<String, Registration> registrationsByRegID = new HashMap<>();
- private Map<String, RegistrationDTO> registrationDTOsByRegID = new HashMap<>();
- private Map<Integer, Set<RegistrationDTO>> registrationDTOsByCitationID = new HashMap<>();
+ private Map<Integer, Registration> registrationsByRegID = new HashMap<>();
+ private Map<Integer, RegistrationDTO> registrationDTOsById = new HashMap<>();
+ private Map<String, RegistrationDTO> registrationDTOsByIdentifier = new HashMap<>();
+ private Map<Integer, List<RegistrationDTO>> registrationDTOsByCitationId = new HashMap<>();
private Collection<CdmBase> cdmEntities = new HashSet<>();
Registration nameReg = new Registration();
nameReg.setName(name);
cdmEntities.add(name);
- try {
- put(nameReg, new RegistrationDTO(nameReg));
- } catch (RegistrationValidationException e) {
- //FIXME throw and handle Exception
- Logger.getLogger(this.getClass()).error(e);
- }
+ put(new RegistrationDTO(nameReg));
// typedesignation
Registration typedesignationReg = new Registration();
typedesignationReg.addTypeDesignations(name.getTypeDesignations());
cdmEntities.addAll(name.getTypeDesignations());
- try {
- put(typedesignationReg, new RegistrationDTO(typedesignationReg));
- } catch (RegistrationValidationException e) {
- //FIXME throw and handle Exception
- Logger.getLogger(this.getClass()).error(e);
- }
+ put(new RegistrationDTO(typedesignationReg));
}
}
}
/**
* @param reg
*/
- private void put(Registration reg, RegistrationDTO dto) {
- registrationsByUUID.put(reg.getUuid(), reg);
- registrationsByRegID.put(reg.getSpecificIdentifier(), reg);
- registrationDTOsByRegID.put(reg.getSpecificIdentifier(), dto);
- if(! registrationDTOsByCitationID.containsKey(dto.getCitationID())){
- registrationDTOsByCitationID.put(dto.getCitationID(), new HashSet<RegistrationDTO>());
+ private void put(RegistrationDTO dto) {
+ Registration reg = dto.registration();
+ registrationsByUUID.put(dto.getUuid(), reg);
+ registrationsByRegID.put(reg.getId(), reg);
+
+ registrationDTOsById.put(reg.getId(), dto);
+ registrationDTOsByIdentifier.put(reg.getIdentifier(), dto);
+
+ if(! registrationDTOsByCitationId.containsKey(dto.getCitationID())){
+ registrationDTOsByCitationId.put(dto.getCitationID(), new ArrayList<RegistrationDTO>());
}
- registrationDTOsByCitationID.get(dto.getCitationID()).add(dto);
+ registrationDTOsByCitationId.get(dto.getCitationID()).add(dto);
}
private void mergeBack(){
return registrationsByUUID.get(uuid);
}
+
public Collection<Registration> list(){
init();
return registrationsByUUID.values();
public Collection<RegistrationDTO> listDTOs() {
init();
- return registrationDTOsByRegID.values();
+ return registrationDTOsById.values();
+ }
+
+ public Map<Integer, List<RegistrationDTO>> listDTOsByWorkingSet() {
+ init();
+ return registrationDTOsByCitationId;
+ }
+
+ /**
+ * @param id the CDM Entity id
+ * @return
+ */
+ public Registration loadByRegistrationID(Integer id) {
+ init();
+ return registrationsByRegID.get(id);
}
- public Map<Integer, Set<RegistrationDTO>> listDTOsByWorkingSet() {
+ /**
+ * @param identifier the Registration Identifier String
+ * @return
+ */
+ public RegistrationDTO loadDtoByIdentifier(String identifier) {
init();
- return registrationDTOsByCitationID;
+ return registrationDTOsById.get(identifier);
}
/**
- * @param registrationID
+ * @param id the CDM Entity id
* @return
*/
- public Registration loadByRegistrationID(Integer registrationID) {
+ public RegistrationDTO loadDtoById(Integer id) {
init();
- return registrationsByRegID.get(registrationID.toString());
+ return registrationDTOsById.get(id);
+ }
+
+ /**
+ * @param id the CDM Entity id
+ * @return
+ * @throws RegistrationValidationException
+ */
+ public RegistrationWorkingSet loadWorkingSetByRegistrationID(Integer id) throws RegistrationValidationException {
+ init();
+ RegistrationDTO dto = registrationDTOsById.get(id);
+
+ return new RegistrationWorkingSet(registrationDTOsByCitationId.get(dto.getCitationID()));
}
import com.vaadin.ui.Link;
import com.vaadin.ui.themes.ValoTheme;
+import eu.etaxonomy.cdm.vaadin.event.ShowDetailsEvent;
import eu.etaxonomy.cdm.vaadin.presenter.registration.RegistrationDTO;
import eu.etaxonomy.cdm.vaadin.presenter.registration.RegistrationType;
import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationTypeConverter;
updateTypeStateLabel();
getCitationSummaryLabel().setValue(regDto.getCitationString() + "</br>" + regDto.getSummary());
updateIdentifierLink();
- getOpenButton().addClickListener(e -> parentView.getEventBus().publishEvent(new NavigationEvent(
+
+ // Buttons
+ getOpenButton().addClickListener(e -> publishEvent(new NavigationEvent(
RegistrationWorkflowViewBean.NAME,
RegistrationWorkflowViewBean.ACTION_EDIT,
- regDto.getSpecificIdentifier().toString()
+ Integer.toString(regDto.getId())
)));
+ if(regDto.getMessages().size() > 0){
+ getMessageButton().setEnabled(true);
+ getMessageButton().addStyleName(ValoTheme.BUTTON_FRIENDLY);
+ getMessageButton().addClickListener(e -> publishEvent(
+ new ShowDetailsEvent<RegistrationDTO, Integer>(
+ e,
+ RegistrationDTO.class,
+ regDto.getId(),
+ "messages"))
+ );
+ }
+
updateDateLabels();
}
*
*/
private void updateIdentifierLink() {
- getIdentifierLink().setResource(new ExternalResource(regDto.getRegistrationId()));
+ getIdentifierLink().setResource(new ExternalResource(regDto.getIdentifier()));
//TODO make responsive and use specificIdetifier in case the space gets too narrow
- getIdentifierLink().setCaption(regDto.getRegistrationId());
+ getIdentifierLink().setCaption(regDto.getIdentifier());
}
/**
}
}
+ private void publishEvent(Object event) {
+ parentView.getEventBus().publishEvent(event);
+ }
+
/* ====== RegistrationItemDesign Getters ====== */
/**
* @return the typeStateLabel
--- /dev/null
+/**
+* Copyright (C) 2017 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.vaadin.event;
+
+import com.vaadin.ui.Component.Event;
+
+/**
+ * A request to display the details of the <code>property</code> for an object of
+ * the class <code>entityType</code> which is uniquely identified by the <code>identifier</code>
+ * This event is usually passed from a view to the according presenter implementation
+ * which is capable of retrieving the details based on the <code>entityType</code> +
+ * <code>identifier</code> + <code>property</code> and which should in turn pass the
+ * extracted details data to the view for display.
+ *
+ * @author a.kohlbecker
+ * @since Mar 24, 2017
+ *
+ */
+public class ShowDetailsEvent<T extends Object, I extends Object> {
+
+ private Event source;
+ private Class<T> entityType;
+ private I identifier;
+ private String property;
+
+ /**
+ *
+ * @param e
+ * @param identifier
+ * @param property
+ */
+ public ShowDetailsEvent(Event e, Class<T> entityType , I identifier, String property) {
+ this.source = e;
+ this.entityType = entityType;
+ this.identifier = identifier;
+ this.property = property;
+ }
+
+ /**
+ * @return the source
+ */
+ public Event getSource() {
+ return source;
+ }
+
+ /**
+ * @return the type
+ */
+ public Class<T> getType() {
+ return entityType;
+ }
+
+ /**
+ * @return the identifier
+ */
+ public I getIdentifier() {
+ return identifier;
+ }
+
+ /**
+ * @return the property
+ */
+ public String getProperty() {
+ return property;
+ }
+
+
+
+}
import java.util.Set;
import eu.etaxonomy.cdm.mock.Registration;
+import eu.etaxonomy.cdm.model.name.TaxonNameBase;
import eu.etaxonomy.cdm.vaadin.presenter.registration.RegistrationDTO;
import eu.etaxonomy.cdm.vaadin.presenter.registration.RegistrationValidationException;
*/
public class RegistrationWorkingSet {
- private Set<Registration> registrations = new HashSet<>();
+ private List<RegistrationDTO> registrationDTOs = new ArrayList<>();
private int citationId = -1;
private String citation = null;
- public RegistrationWorkingSet(Set<Registration> registrations) throws RegistrationValidationException {
+ /**
+ * Creates an empty working set
+ */
+ public RegistrationWorkingSet() {
+
+ }
- validateAndAdd(registrations);
+ public RegistrationWorkingSet(List<RegistrationDTO> registrationDTOs) throws RegistrationValidationException {
+ validateAndAddDTOs(registrationDTOs, null);
}
/**
* @throws RegistrationValidationException
*
*/
- private void validateAndAdd(Set<Registration> candidated) throws RegistrationValidationException {
- List<String> problems = new ArrayList<>();
- for(Registration reg : candidated){
- try {
- RegistrationDTO regDto = new RegistrationDTO(reg);
+ private void validateAndAdd(Set<Registration> candidates) throws RegistrationValidationException {
+ List<RegistrationDTO> dtos = new ArrayList<>(registrationDTOs.size());
+ candidates.forEach(reg -> dtos.add(new RegistrationDTO(reg)));
+ validateAndAddDTOs(dtos, null);
+ }
+
+ /**
+ * Validate and add all Registrations to the working set which are referring to the same publication
+ * which is either the citation of the nomenclatural reference of the {@link TaxonNameBase} or the
+ * citation of the {@link TypeDesignations}. Registration with a differing publication are not added to
+ * the working set, instead a {@link RegistrationValidationException} is thrown which is a container for
+ * all validation problems.
+ *
+ * @param candidates
+ * @param problems Problems detected in prior validation and processing passed to this method to be completed.
+ * @throws RegistrationValidationException
+ */
+ private void validateAndAddDTOs(List<RegistrationDTO> candidates, List<String> problems) throws RegistrationValidationException {
+ if(problems == null){
+ problems = new ArrayList<>();
+ }
+ for(RegistrationDTO regDto : candidates){
if(citationId == -1){
citationId = regDto.getCitationID();
citation = regDto.getCitation();
} else {
if(regDto.getCitationID() != citationId){
- problems.add("Removing Registration " + reg.toString() + " from set since this refers to a different citation.\n");
+ problems.add("Removing Registration " + regDto.registration().toString() + " from set since this refers to a different citation.");
continue;
}
}
- this.registrations.add(reg);
-
- } catch (RegistrationValidationException e) {
- problems.add(e.getMessage());
- }
+ this.registrationDTOs.add(regDto);
}
if(!problems.isEmpty()){
- throw new RegistrationValidationException(problems.toString());
+ throw new RegistrationValidationException("", problems);
}
}
- public boolean add(Registration registration){
- return registrations.add(registration);
+ /**
+ * @param reg
+ * @throws RegistrationValidationException
+ */
+ public void add(Registration reg) throws RegistrationValidationException {
+ Set<Registration> candidates = new HashSet<>();
+ candidates.add(reg);
+ validateAndAdd(candidates);
+ }
+
+ /**
+ * @return the registrations
+ */
+ public List<Registration> getRegistrations() {
+ List<Registration> regs = new ArrayList<>(registrationDTOs.size());
+ registrationDTOs.forEach(dto -> regs.add(dto.registration()));
+ return regs;
}
/**
* @return the registrations
*/
- public Set<Registration> getRegistrations() {
- return registrations;
+ public List<RegistrationDTO> getRegistrationDTOs() {
+ return registrationDTOs;
}
/**
+
}
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import eu.etaxonomy.cdm.mock.RegistrationService;
+import eu.etaxonomy.cdm.vaadin.event.ShowDetailsEvent;
import eu.etaxonomy.cdm.vaadin.view.registration.ListView;
import eu.etaxonomy.vaadin.mvp.AbstractPresenter;
return dtos;
}
+ @EventListener(classes=ShowDetailsEvent.class) // (condition = "#event.entityType == eu.etaxonomy.cdm.vaadin.presenter.registration.RegistrationDTO")
+ public void onShowDetailsEvent(ShowDetailsEvent<?,?> event) { // WARNING don't use more specific generic type arguments
+ RegistrationDTO regDto = serviceMock.loadDtoById((Integer)event.getIdentifier());
+ if(event.getProperty().equals("messages")){
+ getView().openDetailsPopup("Messages", regDto.getMessages());
+ }
+ }
+
}
*/
package eu.etaxonomy.cdm.vaadin.presenter.registration;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
+import java.util.UUID;
import org.joda.time.DateTime;
private Registration reg;
- static int idAutoincrement = 100000;
+ private List<String> messages = new ArrayList<>();
private Set<Registration> blockedBy = new HashSet<>();
/**
* @param reg
* @param typifiedName should be provided in for Registrations for TypeDesignations
- * @throws RegistrationValidationException in case of inconsistencies in the Registration
*/
- public RegistrationDTO(Registration reg) throws RegistrationValidationException {
+ public RegistrationDTO(Registration reg) {
this.reg = reg;
citationID = citation.getId();
}
} else if(registrationType.isTypification()){
- typifiedName = findTypifiedName();
+ try {
+ typifiedName = findTypifiedName();
+ } catch (RegistrationValidationException e) {
+ messages.add("Validation errors: " + e.getMessage());
+ }
summary = new TypeDesignationConverter(reg.getTypeDesignations(), typifiedName)
.buildString().print();
if(!reg.getTypeDesignations().isEmpty()){
} else {
summary = "- INVALID REGISTRATION -";
}
+
+ messages.add("dummy");
}
/**
+ * FIXME use the validation framework validators and to store the validation problems!!!
+ *
* @return
* @throws RegistrationValidationException
*/
private TaxonNameBase<?,?> findTypifiedName() throws RegistrationValidationException {
- StringBuffer problems = new StringBuffer();
+ List<String> problems = new ArrayList<>();
TaxonNameBase<?,?> typifiedName = null;
if(typeDesignation.getTypifiedNames().isEmpty()){
//TODO instead throw RegistrationValidationException()
- problems.append(" - Missing typifiedName in " + typeDesignation.toString()).append("\n");
+ problems.add("Missing typifiedName in " + typeDesignation.toString());
continue;
}
if(typeDesignation.getTypifiedNames().size() > 1){
//TODO instead throw RegistrationValidationException()
- problems.append(" - Multiple typifiedName in " + typeDesignation.toString()).append("\n");
+ problems.add("Multiple typifiedName in " + typeDesignation.toString());
continue;
}
if(typifiedName == null){
TaxonNameBase<?,?> otherTypifiedName = typeDesignation.getTypifiedNames().iterator().next();
if(typifiedName.getId() != otherTypifiedName.getId()){
//TODO instead throw RegistrationValidationException()
- problems.append(" - Multiple typifiedName in " + typeDesignation.toString()).append("\n");
+ problems.add("Multiple typifiedName in " + typeDesignation.toString());
}
}
}
- if(problems.length() > 0){
- throw new RegistrationValidationException("Inconsistent Registration entity. " + reg.toString() + " Problems:\n" + problems.toString());
+ if(!problems.isEmpty()){
+ // FIXME use the validation framework
+ throw new RegistrationValidationException("Inconsistent Registration entity. " + reg.toString(), problems);
}
return typifiedName;
}
+ /**
+ * Provides access to the Registration entity this DTO has been build from.
+ * This method is purposely not a getter to hide the original Registration
+ * from generic processes which are exposing, binding bean properties.
+ *
+ * @return
+ */
+ public Registration registration() {
+ return reg;
+ }
+
/**
* @return the summary
/**
- * @return the registrationId
+ * @return the identifier
*/
- public String getRegistrationId() {
+ public String getIdentifier() {
return reg.getIdentifier();
}
+ public int getId() {
+ return reg.getId();
+ }
+
+
+ public UUID getUuid() {
+ return reg.getUuid();
+ }
+
/**
* @return the specificIdentifier
*/
return citationID;
}
+
+
+ /**
+ * @return
+ */
+ public List<String> getMessages() {
+ return messages;
+ }
+
}
\ No newline at end of file
*/
package eu.etaxonomy.cdm.vaadin.presenter.registration;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* @author a.kohlbecker
* @since Mar 23, 2017
*
*/
+@SuppressWarnings("serial")
public class RegistrationValidationException extends Exception {
+ List<String> problems = new ArrayList<>();
+
/**
* @param message
*/
- public RegistrationValidationException(String message) {
+ public RegistrationValidationException(String message, List<String> problems) {
super(message);
+ this.problems = problems;
+ }
+
+ @Override
+ public String getMessage() {
+ StringBuffer sb = new StringBuffer(super.getMessage()).append(" - Problems:");
+ problems.forEach(p -> sb.append("- ").append(p).append("\n"));
+ return sb.toString();
+ }
+
+ public List<String> getProblems() {
+ return problems;
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
+import com.vaadin.server.SystemError;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
import eu.etaxonomy.cdm.vaadin.event.ReferenceEvent;
import eu.etaxonomy.cdm.vaadin.event.registration.RegistrationWorkflowEvent;
+import eu.etaxonomy.cdm.vaadin.model.registration.RegistrationWorkingSet;
import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationWorkflowView;
import eu.etaxonomy.vaadin.mvp.AbstractPresenter;
@Autowired
private RegistrationService serviceMock;
- private Registration registration;
+ private RegistrationWorkingSet workingset;
/**
*
}
@EventListener
- protected void onRegistrationStartEvent(RegistrationWorkflowEvent e){
+ protected void onRegistrationStartEvent(RegistrationWorkflowEvent event){
- if(registration != null){
- Logger.getLogger(RegistrationWorkflowPresenter.class).warn("Foiling attempt to start another registration in existing workflow");
+ if(workingset != null){
+ Logger.getLogger(RegistrationWorkflowPresenter.class).warn("Cant start a new workflow over an existing one.");
return;
}
- if(e.isStart()) {
- registration = new Registration();
- registration.setName(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()));
- getView().setHeaderText("New " + e.getType().name().toString()+ " Registration");
+
+ if(event.isStart()) {
+ workingset = new RegistrationWorkingSet();
+ Registration reg = new Registration();
+ reg.setName(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()));
+ getView().setHeaderText("New " + event.getType().name().toString()+ " Registration");
+ try {
+ workingset.add(reg);
+ } catch (RegistrationValidationException error) {
+ getView().getWorkflow().setComponentError(new SystemError(error));
+ }
} else {
- registration = serviceMock.loadByRegistrationID(e.getRegistrationID());
- getView().setHeaderText("Registration " + registration.getIdentifier());
+ try {
+ workingset = serviceMock.loadWorkingSetByRegistrationID(event.getRegistrationID());
+ } catch (RegistrationValidationException error) {
+ getView().getWorkflow().setComponentError(new SystemError(error));
+ }
+ getView().setHeaderText("Registration for " + workingset.getCitation());
}
- if(registration != null){
+ if(workingset != null){
// getView().getTitle().setValue("Workflow for a " + registrationType().name());
- getView().makeWorflow(registrationType());
+ for(Registration reg : workingset.getRegistrations()){
+ getView().makeWorflow(RegistrationType.from(reg));
+ }
}
}
getView().openReferenceEditor(null);
}
-
- /**
- * @return
- */
- private RegistrationType registrationType() {
- return RegistrationType.from(registration);
- }
-
-
-
}
package eu.etaxonomy.cdm.vaadin.view.registration;
import java.util.Collection;
+import java.util.List;
import eu.etaxonomy.cdm.vaadin.presenter.registration.ListPresenter;
import eu.etaxonomy.cdm.vaadin.presenter.registration.RegistrationDTO;
*/
void populate(Collection<RegistrationDTO> registrations);
+ /**
+ * @param messages
+ */
+ void openDetailsPopup(String caption, List<String> messages);
+
}
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.vaadin.data.util.PropertyValueGenerator;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
+import com.vaadin.server.Page;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.ui.Button;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.Column;
import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.renderers.ButtonRenderer;
import com.vaadin.ui.renderers.DateRenderer;
import com.vaadin.ui.renderers.HtmlRenderer;
Column summaryColumn = grid.addColumn("summary");
- Column regidColumn = grid.addColumn("registrationId");
+ Column regidColumn = grid.addColumn("identifier");
regidColumn.setHeaderCaption("Id");
regidColumn.setRenderer(new HtmlRenderer(), new UrlStringConverter("http://pyhcobank.org/"));
public void populateList(Collection<RegistrationDTO> registrations) {
for(RegistrationDTO regDto : registrations) {
- Component lazyItem = new RegistrationItem(regDto, this); //new LazyLoadWrapper(new RegistrationItem(regDto, this));
- lazyItem.setWidth(100, Unit.PERCENTAGE);
- listContainer.addComponent(lazyItem);
+ Component item = new RegistrationItem(regDto, this);
+ item.setWidth(100, Unit.PERCENTAGE);
+ listContainer.addComponent(item);
}
}
+ @Override
+ public void openDetailsPopup(String caption, List<String> messages){
+ StringBuffer sb = new StringBuffer();
+ sb.append("<div class=\"details-popup-content\">");
+ messages.forEach(s -> sb.append(s).append("</br>"));
+ sb.append("</div>");
+ new Notification(caption, sb.toString(), Notification.Type.HUMANIZED_MESSAGE, true).show(Page.getCurrent());
+ }
+
/**
* @param registrationItems
* @return