2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.vaadin
.component
.registration
;
11 import java
.util
.ArrayList
;
12 import java
.util
.Collection
;
13 import java
.util
.Collections
;
14 import java
.util
.EnumSet
;
15 import java
.util
.List
;
17 import java
.util
.UUID
;
19 import org
.apache
.logging
.log4j
.LogManager
;
20 import org
.apache
.logging
.log4j
.Logger
;
22 import com
.vaadin
.server
.ExternalResource
;
23 import com
.vaadin
.server
.FontAwesome
;
24 import com
.vaadin
.shared
.ui
.label
.ContentMode
;
25 import com
.vaadin
.ui
.Button
;
26 import com
.vaadin
.ui
.Label
;
27 import com
.vaadin
.ui
.Link
;
28 import com
.vaadin
.ui
.themes
.ValoTheme
;
30 import eu
.etaxonomy
.cdm
.api
.service
.dto
.RegistrationWrapperDTO
;
31 import eu
.etaxonomy
.cdm
.api
.service
.name
.TypeDesignationDTO
;
32 import eu
.etaxonomy
.cdm
.api
.service
.name
.TypeDesignationSet
;
33 import eu
.etaxonomy
.cdm
.api
.service
.name
.TypeDesignationSet
.TypeDesignationSetType
;
34 import eu
.etaxonomy
.cdm
.api
.util
.UserHelper
;
35 import eu
.etaxonomy
.cdm
.model
.ICdmEntityUuidCacher
;
36 import eu
.etaxonomy
.cdm
.model
.common
.VersionableEntity
;
37 import eu
.etaxonomy
.cdm
.model
.name
.RegistrationStatus
;
38 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
39 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationStatusBase
;
40 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
41 import eu
.etaxonomy
.cdm
.model
.permission
.CRUD
;
42 import eu
.etaxonomy
.cdm
.ref
.TypedEntityReference
;
43 import eu
.etaxonomy
.cdm
.service
.UserHelperAccess
;
44 import eu
.etaxonomy
.cdm
.strategy
.cache
.TagEnum
;
45 import eu
.etaxonomy
.cdm
.strategy
.cache
.TaggedTextFormatter
;
46 import eu
.etaxonomy
.cdm
.vaadin
.component
.ButtonFactory
;
47 import eu
.etaxonomy
.cdm
.vaadin
.model
.registration
.RegistrationTermLists
.RegistrationTypeDesignationStatusComparator
;
48 import eu
.etaxonomy
.cdm
.vaadin
.permission
.PermissionDebugUtils
;
49 import eu
.etaxonomy
.vaadin
.component
.CompositeStyledComponent
;
52 * @author a.kohlbecker
55 public class RegistrationItemNameAndTypeButtons
extends CompositeStyledComponent
{
57 private static final Logger logger
= LogManager
.getLogger();
59 private static final String DEFAULT_BUTTON_STYLES
= "";
61 private static final long serialVersionUID
= -5059163772392864050L;
63 private static final String STYLE_NAMES
= "edit-button-group " + ValoTheme
.LAYOUT_COMPONENT_GROUP
;
65 private IdButton
<TaxonName
> nameIdButton
= null;
67 private List
<TypeDesignationSetButton
> typeDesignationButtons
= new ArrayList
<>();
69 private List
<Label
> labels
= new ArrayList
<>();
71 private List
<ButtonWithUserEditPermission
> editButtons
= new ArrayList
<>();
73 private Button addTypeDesignationButton
;
75 private Label nameLabel
= null;
77 private Link identifierLink
;
79 private boolean isRegistrationLocked
;
81 private boolean isLockOverride
;
83 private boolean userHasAddPermission
;
85 public RegistrationItemNameAndTypeButtons(RegistrationWrapperDTO regDto
, ICdmEntityUuidCacher entitiyCacher
) {
87 isRegistrationLocked
= EnumSet
.of(
88 RegistrationStatus
.PUBLISHED
, RegistrationStatus
.REJECTED
)
89 .contains(regDto
.getStatus());
91 setWidth(100, Unit
.PERCENTAGE
);
93 UserHelper userHelper
;
94 if(entitiyCacher
!= null){
95 userHelper
= UserHelperAccess
.userHelper().withCache(entitiyCacher
);
97 userHelper
= UserHelperAccess
.userHelper();
100 if(regDto
.getNameRef() != null){
101 Button nameButton
= new Button("Name:");
102 nameButton
.setDescription("Edit the Name");
103 nameIdButton
= new IdButton
<TaxonName
>(TaxonName
.class, regDto
.getNameRef().getUuid(), nameButton
);
104 Label nameLabel
= new Label(regDto
.getNameRef().getLabel());
105 nameLabel
.setWidthUndefined();
106 boolean userHasPermission
= userHelper
.userHasPermission(regDto
.registration().getName(), CRUD
.UPDATE
);
107 editButtons
.add(new ButtonWithUserEditPermission(nameButton
, userHasPermission
));
109 addComponent(nameIdButton
.getButton());
110 PermissionDebugUtils
.addGainPerEntityPermissionButton(this, TaxonName
.class, regDto
.getNameRef().getUuid(),
111 EnumSet
.of(CRUD
.UPDATE
, CRUD
.DELETE
), null);
112 addComponent(nameLabel
);
114 // no name in the registration! we only show the typified name as label
115 if(regDto
.getTypifiedNameRef() != null){
116 nameLabel
= new Label(regDto
.getTypifiedNameRef().getLabel());
117 addComponent(nameLabel
);
121 userHasAddPermission
= !regDto
.isPersisted() || userHelper
.userHasPermission(regDto
.registration(), CRUD
.UPDATE
);
122 Map
<TypedEntityReference
<?
extends VersionableEntity
>,TypeDesignationSet
> typeDesignationSets
= regDto
.getOrderedTypeDesignationSets();
124 if(typeDesignationSets
!= null){
125 // order the typeDesignationSet keys so that holotypes come first, etc
126 List
<TypedEntityRefWithStatus
> baseRefsByHighestStatus
= new ArrayList
<>();
127 for(TypedEntityReference
<?
extends VersionableEntity
> baseEntityRef
: typeDesignationSets
.keySet()) {
128 baseRefsByHighestStatus
.add(new TypedEntityRefWithStatus(baseEntityRef
, typeDesignationSets
.get(baseEntityRef
).highestTypeStatus(new RegistrationTypeDesignationStatusComparator())));
131 Collections
.sort(baseRefsByHighestStatus
);
133 for(TypedEntityRefWithStatus typedEntityRefWithStatus
: baseRefsByHighestStatus
) {
134 TypedEntityReference
<?
extends VersionableEntity
> baseEntity
= typedEntityRefWithStatus
.typedEntity
;
135 TypeDesignationSet typeDesignationSet
= typeDesignationSets
.get(baseEntity
);
136 if (logger
.isDebugEnabled()) {logger
.debug("WorkingSet:" + typeDesignationSet
.getWorkingsetType() + ">" + typeDesignationSet
.getBaseEntity().toString());}
137 String buttonLabel
= SpecimenOrObservationBase
.class.isAssignableFrom(baseEntity
.getType()) ?
"Type": "NameType";
138 Button tdButton
= new Button(buttonLabel
+ ":");
139 tdButton
.setDescription("Edit the type designation working set");
140 boolean userHasUpdatePermission
= userHelper
.userHasPermission(baseEntity
.getType(), baseEntity
.getUuid(), CRUD
.UPDATE
, CRUD
.DELETE
);
141 editButtons
.add(new ButtonWithUserEditPermission(tdButton
, userHasUpdatePermission
));
142 addComponent(tdButton
);
144 PermissionDebugUtils
.addGainPerEntityPermissionButton(this, SpecimenOrObservationBase
.class,
145 baseEntity
.getUuid(), EnumSet
.of(CRUD
.UPDATE
, CRUD
.DELETE
), RegistrationStatus
.PREPARATION
.name());
147 typeDesignationButtons
.add(new TypeDesignationSetButton(
148 typeDesignationSet
.getWorkingsetType(),
149 typeDesignationSet
.getBaseEntity(),
153 String labelText
= "<span class=\"field-unit-label\">" + baseEntity
.getLabel() + "</span>"; // renders the FieldUnit label
154 for(TypeDesignationStatusBase
<?
> typeStatus
: typeDesignationSet
.keySet()){
155 Collection
<TypeDesignationDTO
> tdPerStatus
= typeDesignationSet
.get(typeStatus
);
156 labelText
+= " <strong>" + typeStatus
.getLabel() + (tdPerStatus
.size() > 1 ?
"s":"" ) + "</strong>: ";
157 boolean isFirst
= true;
158 for(TypeDesignationDTO
<?
> dtDTO
: tdPerStatus
) {
159 labelText
+= ( isFirst ?
"" : ", ") + TaggedTextFormatter
.createString(
160 TaggedTextFormatter
.cropAt(dtDTO
.getTaggedText(), TagEnum
.separator
, "designated\\s+[bB]y"));
165 Label label
= new Label(labelText
, ContentMode
.HTML
);
166 label
.setWidthUndefined();
171 addTypeDesignationButton
= ButtonFactory
.ADD_ITEM
.createButton();
172 addTypeDesignationButton
.setDescription("Add a new type designation workingset.");
173 addComponent(addTypeDesignationButton
);
175 //TODO make responsive and use specificIdentifier in case the space gets too narrow
176 if(regDto
.isPersisted()){
177 identifierLink
= new Link(regDto
.getIdentifier(), new ExternalResource(regDto
.getIdentifier()));
178 identifierLink
.setEnabled(regDto
.getStatus() == RegistrationStatus
.PUBLISHED
);
179 addComponents(identifierLink
);
182 iterator().forEachRemaining(c
-> addStyledComponent(c
));
183 updateEditorButtonReadonlyStates();
187 private void updateEditorButtonReadonlyStates() {
188 for(ButtonWithUserEditPermission b
: editButtons
){
189 boolean impossibleToUnlock
= !b
.userCanEdit
&& isLockOverride
&& isRegistrationLocked
;
190 b
.button
.setReadOnly((isRegistrationLocked
&& !isLockOverride
) || !b
.userCanEdit
);
191 b
.button
.setEnabled(!impossibleToUnlock
);
192 b
.button
.setDescription(impossibleToUnlock ?
"Unlock failed due to missing permissions!" : "");
193 b
.button
.setIcon(isLockOverride ? FontAwesome
.UNLOCK_ALT
: null);
196 //by AM to fix #10435
197 boolean addTypeDesignationButtonVisible
= (!isRegistrationLocked
|| isLockOverride
)
198 && userHasAddPermission
;
199 addTypeDesignationButton
.setVisible(addTypeDesignationButtonVisible
);
202 public IdButton
<TaxonName
> getNameButton() {
206 public List
<TypeDesignationSetButton
> getTypeDesignationButtons() {
207 return typeDesignationButtons
;
210 public Button
getAddTypeDesignationButton() {
211 return addTypeDesignationButton
;
215 protected void addDefaultStyles() {
216 addStyleName(STYLE_NAMES
);
217 if(nameIdButton
!= null){
218 nameIdButton
.getButton().addStyleName(DEFAULT_BUTTON_STYLES
);
220 if(nameLabel
!= null){
221 nameLabel
.addStyleName("v-disabled");
223 typeDesignationButtons
.forEach(idb
-> idb
.getButton().addStyleName(DEFAULT_BUTTON_STYLES
));
224 addTypeDesignationButton
.addStyleName(DEFAULT_BUTTON_STYLES
);
227 public class TypeDesignationSetButton
{
229 private VersionableEntity baseEntity
;
230 private TypeDesignationSetType type
;
231 private Button button
;
233 public TypeDesignationSetButton(TypeDesignationSetType type
, VersionableEntity baseEntity
, Button button
){
235 this.baseEntity
= baseEntity
;
236 this.button
= button
;
239 public VersionableEntity
getBaseEntity() {
243 public Button
getButton() {
247 public TypeDesignationSetType
getType() {
252 public class IdButton
<T
> {
254 private Class
<T
> entityType
;
255 private Button button
;
257 public IdButton(Class
<T
> type
, UUID uuid
, Button button
){
258 this.entityType
= type
;
260 this.button
= button
;
263 public UUID
getUuid() {
267 public Button
getButton() {
271 public Class
<T
> getType() {
276 public class ButtonWithUserEditPermission
{
280 public ButtonWithUserEditPermission(Button button
, boolean userCanEdit
) {
282 this.button
= button
;
283 this.userCanEdit
= userCanEdit
;
287 public boolean isRegistrationLocked() {
288 return isRegistrationLocked
;
291 public boolean isLockOverride() {
292 return isLockOverride
;
295 public void setLockOverride(boolean isLockOverride
) {
296 if(this.isLockOverride
!= isLockOverride
){
297 this.isLockOverride
= isLockOverride
;
298 updateEditorButtonReadonlyStates();
302 private class TypedEntityRefWithStatus
implements Comparable
<TypedEntityRefWithStatus
> {
304 public TypedEntityReference
<?
extends VersionableEntity
> typedEntity
;
305 public TypeDesignationStatusBase
<?
> status
;
306 private RegistrationTypeDesignationStatusComparator comparator
= new RegistrationTypeDesignationStatusComparator();
308 public TypedEntityRefWithStatus(TypedEntityReference
<?
extends VersionableEntity
> typedEntity
,
309 TypeDesignationStatusBase
<?
> status
) {
310 this.typedEntity
= typedEntity
;
311 this.status
= status
;
315 public int compareTo(TypedEntityRefWithStatus o
) {
316 return comparator
.compare(this.status
, o
.status
);