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
.RegistrationDTO
;
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
.TaggedCacheHelper
;
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 public 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 public RegistrationItemNameAndTypeButtons(RegistrationDTO regDto
, ICdmEntityUuidCacher entitiyCacher
) {
85 isRegistrationLocked
= EnumSet
.of(
86 RegistrationStatus
.PUBLISHED
, RegistrationStatus
.REJECTED
)
87 .contains(regDto
.getStatus());
89 setWidth(100, Unit
.PERCENTAGE
);
91 UserHelper userHelper
;
92 if(entitiyCacher
!= null){
93 userHelper
= UserHelperAccess
.userHelper().withCache(entitiyCacher
);
95 userHelper
= UserHelperAccess
.userHelper();
98 if(regDto
.getNameRef() != null){
99 Button nameButton
= new Button("Name:");
100 nameButton
.setDescription("Edit the Name");
101 nameIdButton
= new IdButton
<TaxonName
>(TaxonName
.class, regDto
.getNameRef().getUuid(), nameButton
);
102 Label nameLabel
= new Label(regDto
.getNameRef().getLabel());
103 nameLabel
.setWidthUndefined();
104 boolean userHasPermission
= userHelper
.userHasPermission(regDto
.registration().getName(), CRUD
.UPDATE
);
105 editButtons
.add(new ButtonWithUserEditPermission(nameButton
, userHasPermission
));
107 addComponent(nameIdButton
.getButton());
108 PermissionDebugUtils
.addGainPerEntityPermissionButton(this, TaxonName
.class, regDto
.getNameRef().getUuid(),
109 EnumSet
.of(CRUD
.UPDATE
, CRUD
.DELETE
), null);
110 addComponent(nameLabel
);
112 // no name in the registration! we only show the typified name as label
113 if(regDto
.getTypifiedNameRef() != null){
114 nameLabel
= new Label(regDto
.getTypifiedNameRef().getLabel());
115 addComponent(nameLabel
);
118 boolean userHasAddPermission
= !regDto
.isPersisted() || userHelper
.userHasPermission(regDto
.registration(), CRUD
.UPDATE
);
119 Map
<TypedEntityReference
<?
extends VersionableEntity
>,TypeDesignationSet
> typeDesignationSets
= regDto
.getOrderedTypeDesignationSets();
121 if(typeDesignationSets
!= null){
122 // order the typeDesignationSet keys so that holotypes come first, etc
123 List
<TypedEntityRefWithStatus
> baseRefsByHighestStatus
= new ArrayList
<>();
124 for(TypedEntityReference
<?
extends VersionableEntity
> baseEntityRef
: typeDesignationSets
.keySet()) {
125 baseRefsByHighestStatus
.add(new TypedEntityRefWithStatus(baseEntityRef
, typeDesignationSets
.get(baseEntityRef
).highestTypeStatus(new RegistrationTypeDesignationStatusComparator())));
128 Collections
.sort(baseRefsByHighestStatus
);
130 for(TypedEntityRefWithStatus typedEntityRefWithStatus
: baseRefsByHighestStatus
) {
131 TypedEntityReference
<?
extends VersionableEntity
> baseEntity
= typedEntityRefWithStatus
.typedEntity
;
132 TypeDesignationSet typeDesignationSet
= typeDesignationSets
.get(baseEntity
);
133 if (logger
.isDebugEnabled()) {logger
.debug("WorkingSet:" + typeDesignationSet
.getWorkingsetType() + ">" + typeDesignationSet
.getBaseEntity().toString());}
134 String buttonLabel
= SpecimenOrObservationBase
.class.isAssignableFrom(baseEntity
.getType()) ?
"Type": "NameType";
135 Button tdButton
= new Button(buttonLabel
+ ":");
136 tdButton
.setDescription("Edit the type designation working set");
137 boolean userHasUpdatePermission
= userHelper
.userHasPermission(baseEntity
.getType(), baseEntity
.getUuid(), CRUD
.UPDATE
, CRUD
.DELETE
);
138 editButtons
.add(new ButtonWithUserEditPermission(tdButton
, userHasUpdatePermission
));
139 addComponent(tdButton
);
141 PermissionDebugUtils
.addGainPerEntityPermissionButton(this, SpecimenOrObservationBase
.class,
142 baseEntity
.getUuid(), EnumSet
.of(CRUD
.UPDATE
, CRUD
.DELETE
), RegistrationStatus
.PREPARATION
.name());
144 typeDesignationButtons
.add(new TypeDesignationSetButton(
145 typeDesignationSet
.getWorkingsetType(),
146 typeDesignationSet
.getBaseEntity(),
150 String labelText
= "<span class=\"field-unit-label\">" + baseEntity
.getLabel() + "</span>"; // renders the FieldUnit label
151 for(TypeDesignationStatusBase
<?
> typeStatus
: typeDesignationSet
.keySet()){
152 Collection
<TypeDesignationDTO
> tdPerStatus
= typeDesignationSet
.get(typeStatus
);
153 labelText
+= " <strong>" + typeStatus
.getLabel() + (tdPerStatus
.size() > 1 ?
"s":"" ) + "</strong>: ";
154 boolean isFirst
= true;
155 for(TypeDesignationDTO
<?
> dtDTO
: tdPerStatus
) {
156 labelText
+= ( isFirst ?
"" : ", ") + TaggedCacheHelper
.createString(
157 TaggedCacheHelper
.cropAt(dtDTO
.getTaggedText(), TagEnum
.separator
, "designated\\s+[bB]y"));
162 Label label
= new Label(labelText
, ContentMode
.HTML
);
163 label
.setWidthUndefined();
168 addTypeDesignationButton
= ButtonFactory
.ADD_ITEM
.createButton();
169 addTypeDesignationButton
.setDescription("Add a new type designation workingset.");
170 addTypeDesignationButton
.setVisible(!isRegistrationLocked
&& userHasAddPermission
);
171 addComponent(addTypeDesignationButton
);
173 //TODO make responsive and use specificIdentifier in case the space gets too narrow
174 if(regDto
.isPersisted()){
175 identifierLink
= new Link(regDto
.getIdentifier(), new ExternalResource(regDto
.getIdentifier()));
176 identifierLink
.setEnabled(regDto
.getStatus() == RegistrationStatus
.PUBLISHED
);
177 addComponents(identifierLink
);
180 iterator().forEachRemaining(c
-> addStyledComponent(c
));
181 updateEditorButtonReadonlyStates();
185 private void updateEditorButtonReadonlyStates() {
186 for(ButtonWithUserEditPermission b
: editButtons
){
187 boolean impossibleToUnlock
= !b
.userCanEdit
&& isLockOverride
&& isRegistrationLocked
;
188 b
.button
.setReadOnly((isRegistrationLocked
&& !isLockOverride
) || !b
.userCanEdit
);
189 b
.button
.setEnabled(!impossibleToUnlock
);
190 b
.button
.setDescription(impossibleToUnlock ?
"Unlock failed due to missing permissions!" : "");
191 b
.button
.setIcon(isLockOverride ? FontAwesome
.UNLOCK_ALT
: null);
195 public IdButton
<TaxonName
> getNameButton() {
199 public List
<TypeDesignationSetButton
> getTypeDesignationButtons() {
200 return typeDesignationButtons
;
203 public Button
getAddTypeDesignationButton() {
204 return addTypeDesignationButton
;
208 protected void addDefaultStyles() {
209 addStyleName(STYLE_NAMES
);
210 if(nameIdButton
!= null){
211 nameIdButton
.getButton().addStyleName(DEFAULT_BUTTON_STYLES
);
213 if(nameLabel
!= null){
214 nameLabel
.addStyleName("v-disabled");
216 typeDesignationButtons
.forEach(idb
-> idb
.getButton().addStyleName(DEFAULT_BUTTON_STYLES
));
217 addTypeDesignationButton
.addStyleName(DEFAULT_BUTTON_STYLES
);
220 public class TypeDesignationSetButton
{
222 private VersionableEntity baseEntity
;
223 private TypeDesignationSetType type
;
224 private Button button
;
226 public TypeDesignationSetButton(TypeDesignationSetType type
, VersionableEntity baseEntity
, Button button
){
228 this.baseEntity
= baseEntity
;
229 this.button
= button
;
232 public VersionableEntity
getBaseEntity() {
236 public Button
getButton() {
240 public TypeDesignationSetType
getType() {
245 public class IdButton
<T
> {
247 private Class
<T
> entityType
;
248 private Button button
;
250 public IdButton(Class
<T
> type
, UUID uuid
, Button button
){
251 this.entityType
= type
;
253 this.button
= button
;
256 public UUID
getUuid() {
260 public Button
getButton() {
264 public Class
<T
> getType() {
269 public class ButtonWithUserEditPermission
{
273 public ButtonWithUserEditPermission(Button button
, boolean userCanEdit
) {
275 this.button
= button
;
276 this.userCanEdit
= userCanEdit
;
280 public boolean isRegistrationLocked() {
281 return isRegistrationLocked
;
284 public boolean isLockOverride() {
285 return isLockOverride
;
288 public void setLockOverride(boolean isLockOverride
) {
289 if(this.isLockOverride
!= isLockOverride
){
290 this.isLockOverride
= isLockOverride
;
291 updateEditorButtonReadonlyStates();
295 private class TypedEntityRefWithStatus
implements Comparable
<TypedEntityRefWithStatus
> {
297 public TypedEntityReference
<?
extends VersionableEntity
> typedEntity
;
298 public TypeDesignationStatusBase
<?
> status
;
299 private RegistrationTypeDesignationStatusComparator comparator
= new RegistrationTypeDesignationStatusComparator();
301 public TypedEntityRefWithStatus(TypedEntityReference
<?
extends VersionableEntity
> typedEntity
,
302 TypeDesignationStatusBase
<?
> status
) {
303 this.typedEntity
= typedEntity
;
304 this.status
= status
;
308 public int compareTo(TypedEntityRefWithStatus o
) {
309 return comparator
.compare(this.status
, o
.status
);