From 5c140fd98f5ec7f89663e4af6ab174c206dda0a5 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Tue, 29 Nov 2022 19:35:41 +0100 Subject: [PATCH] Some missing IdResolvers, added scope attributes to all @JsonIdentityInfo annoations --- .../librecms/assets/ContactableEntity.java | 3 +- .../org/librecms/assets/Organization.java | 3 +- .../main/java/org/librecms/assets/Person.java | 4 +- .../org/librecms/assets/PostalAddress.java | 3 +- .../librecms/contentsection/ContentItem.java | 3 +- .../librecms/contentsection/ContentType.java | 3 +- .../org/librecms/contentsection/Folder.java | 3 +- .../org/librecms/lifecycle/Lifecycle.java | 3 +- .../lifecycle/LifecycleDefinition.java | 3 +- .../java/org/librecms/lifecycle/Phase.java | 3 +- .../librecms/lifecycle/PhaseDefinition.java | 3 +- .../categorization/Categorization.java | 4 +- .../CategorizationIdResolver.java | 51 +++++++++++++++ .../CategorizationRepository.java | 54 +++++++++++++++ .../org/libreccm/categorization/Category.java | 3 +- .../org/libreccm/categorization/Domain.java | 9 ++- .../categorization/DomainOwnership.java | 8 ++- .../DomainOwnershipIdResolver.java | 51 +++++++++++++++ .../DomainOwnershipRepository.java | 54 +++++++++++++++ .../java/org/libreccm/core/CcmObject.java | 15 +++-- .../main/java/org/libreccm/core/Resource.java | 26 ++++---- .../java/org/libreccm/core/ResourceType.java | 14 ++-- .../java/org/libreccm/security/Group.java | 26 ++++---- .../libreccm/security/GroupMembership.java | 4 +- .../security/GroupMembershipIdResolver.java | 51 +++++++++++++++ .../security/GroupMembershipRepository.java | 54 +++++++++++++++ .../java/org/libreccm/security/Party.java | 9 ++- .../org/libreccm/security/Permission.java | 9 ++- .../main/java/org/libreccm/security/Role.java | 53 +++++++-------- .../org/libreccm/security/RoleMembership.java | 8 ++- .../security/RoleMembershipIdResolver.java | 51 +++++++++++++++ .../security/RoleMembershipRepository.java | 52 +++++++++++++++ .../main/java/org/libreccm/security/User.java | 9 ++- .../java/org/libreccm/web/CcmApplication.java | 13 ++-- .../org/libreccm/workflow/AssignableTask.java | 24 ++++--- .../main/java/org/libreccm/workflow/Task.java | 28 ++++---- .../org/libreccm/workflow/TaskAssignment.java | 3 +- .../workflow/TaskAssignmentIdResolver.java | 50 ++++++++++++++ .../workflow/TaskAssignmentRepository.java | 59 +++++++++++++++++ .../org/libreccm/workflow/TaskComment.java | 25 +++---- .../org/libreccm/workflow/TaskDependency.java | 6 +- .../workflow/TaskDependencyIdResolver.java | 51 +++++++++++++++ .../workflow/TaskDependencyRepository.java | 65 +++++++++++++++++++ .../java/org/libreccm/workflow/Workflow.java | 12 ++-- 44 files changed, 833 insertions(+), 152 deletions(-) create mode 100644 ccm-core/src/main/java/org/libreccm/categorization/CategorizationIdResolver.java create mode 100644 ccm-core/src/main/java/org/libreccm/categorization/CategorizationRepository.java create mode 100644 ccm-core/src/main/java/org/libreccm/categorization/DomainOwnershipIdResolver.java create mode 100644 ccm-core/src/main/java/org/libreccm/categorization/DomainOwnershipRepository.java create mode 100644 ccm-core/src/main/java/org/libreccm/security/GroupMembershipIdResolver.java create mode 100644 ccm-core/src/main/java/org/libreccm/security/GroupMembershipRepository.java create mode 100644 ccm-core/src/main/java/org/libreccm/security/RoleMembershipIdResolver.java create mode 100644 ccm-core/src/main/java/org/libreccm/security/RoleMembershipRepository.java create mode 100644 ccm-core/src/main/java/org/libreccm/workflow/TaskAssignmentIdResolver.java create mode 100644 ccm-core/src/main/java/org/libreccm/workflow/TaskAssignmentRepository.java create mode 100644 ccm-core/src/main/java/org/libreccm/workflow/TaskDependencyIdResolver.java create mode 100644 ccm-core/src/main/java/org/libreccm/workflow/TaskDependencyRepository.java diff --git a/ccm-cms/src/main/java/org/librecms/assets/ContactableEntity.java b/ccm-cms/src/main/java/org/librecms/assets/ContactableEntity.java index 1a1a67a19..2a03e45f2 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/ContactableEntity.java +++ b/ccm-cms/src/main/java/org/librecms/assets/ContactableEntity.java @@ -52,7 +52,8 @@ import static org.librecms.CmsConstants.*; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = ContactableEntityIdResolver.class, - property = "uuid" + property = "uuid", + scope = ContactableEntity.class ) public class ContactableEntity extends Asset { diff --git a/ccm-cms/src/main/java/org/librecms/assets/Organization.java b/ccm-cms/src/main/java/org/librecms/assets/Organization.java index 501259279..44d843ea1 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/Organization.java +++ b/ccm-cms/src/main/java/org/librecms/assets/Organization.java @@ -56,7 +56,8 @@ import static org.librecms.assets.AssetConstants.*; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = OrganizationIdResolver.class, - property = "uuid" + property = "uuid", + scope = Organization.class ) public class Organization extends ContactableEntity { diff --git a/ccm-cms/src/main/java/org/librecms/assets/Person.java b/ccm-cms/src/main/java/org/librecms/assets/Person.java index 431e7e78a..fad94df5a 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/Person.java +++ b/ccm-cms/src/main/java/org/librecms/assets/Person.java @@ -18,7 +18,6 @@ */ package org.librecms.assets; - import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import org.hibernate.envers.Audited; @@ -71,7 +70,8 @@ import static org.librecms.assets.AssetConstants.*; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = PersonIdResolver.class, - property = "uuid" + property = "uuid", + scope = Person.class ) public class Person extends ContactableEntity { diff --git a/ccm-cms/src/main/java/org/librecms/assets/PostalAddress.java b/ccm-cms/src/main/java/org/librecms/assets/PostalAddress.java index 49755efe1..4d128dafa 100644 --- a/ccm-cms/src/main/java/org/librecms/assets/PostalAddress.java +++ b/ccm-cms/src/main/java/org/librecms/assets/PostalAddress.java @@ -57,7 +57,8 @@ import static org.librecms.assets.AssetConstants.ASSETS_BUNDLE; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = PostalAddressIdResolver.class, - property = "uuid" + property = "uuid", + scope = PostalAddress.class ) public class PostalAddress extends Asset { diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java index 7bc051813..e78a2cc74 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java @@ -580,7 +580,8 @@ import javax.xml.bind.annotation.XmlElementWrapper; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = ContentItemIdResolver.class, - property = "uuid" + property = "uuid", + scope = ContentItem.class ) public class ContentItem extends CcmObject implements Serializable, Exportable { diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentType.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentType.java index 614b6d994..5ec07dcf6 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentType.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentType.java @@ -80,7 +80,8 @@ import static org.librecms.CmsConstants.*; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = ContentTypeIdResolver.class, - property = "uuid" + property = "uuid", + scope = ContentType.class ) public class ContentType extends CcmObject implements Serializable { diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java b/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java index 8580c5086..0029a10ae 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java @@ -310,7 +310,8 @@ import static org.librecms.CmsConstants.*; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = FolderIdResolver.class, - property = "uuid" + property = "uuid", + scope = Folder.class ) public class Folder extends Category implements Serializable { diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/Lifecycle.java b/ccm-cms/src/main/java/org/librecms/lifecycle/Lifecycle.java index 3a041f638..521219825 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/Lifecycle.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/Lifecycle.java @@ -66,7 +66,8 @@ import static org.librecms.CmsConstants.*; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = LifecycleIdResolver.class, - property = "uuid" + property = "uuid", + scope = Lifecycle.class ) public class Lifecycle implements Exportable, Identifiable, Serializable { diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleDefinition.java b/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleDefinition.java index 766ab40a5..85629fdb4 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleDefinition.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleDefinition.java @@ -65,7 +65,8 @@ import static org.librecms.CmsConstants.*; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = LifecycleDefinitionIdResolver.class, - property = "uuid" + property = "uuid", + scope = LifecycleDefinition.class ) public class LifecycleDefinition implements Identifiable, Exportable, Serializable { diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/Phase.java b/ccm-cms/src/main/java/org/librecms/lifecycle/Phase.java index 5a4f39b1f..38e3ab0cb 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/Phase.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/Phase.java @@ -58,7 +58,8 @@ import static org.librecms.CmsConstants.*; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = PhaseIdResolver.class, - property = "uuid" + property = "uuid", + scope = Phase.class ) public class Phase implements Exportable, Serializable { diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinition.java b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinition.java index 28ed153d8..8d151e31c 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinition.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinition.java @@ -57,7 +57,8 @@ import static org.librecms.CmsConstants.*; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = PhaseDefinitionIdResolver.class, - property = "uuid" + property = "uuid", + scope = PhaseDefinition.class ) public class PhaseDefinition implements Exportable, Serializable { diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Categorization.java b/ccm-core/src/main/java/org/libreccm/categorization/Categorization.java index 8450cd68f..c7d96de93 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/Categorization.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/Categorization.java @@ -104,7 +104,9 @@ import javax.persistence.Table; }) @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, - property = "uuid" + resolver = CategorizationIdResolver.class, + property = "uuid", + scope = Categorization.class ) public class Categorization implements Serializable, Relation, Exportable { diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategorizationIdResolver.java b/ccm-core/src/main/java/org/libreccm/categorization/CategorizationIdResolver.java new file mode 100644 index 000000000..fa7ec93f4 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/categorization/CategorizationIdResolver.java @@ -0,0 +1,51 @@ +package org.libreccm.categorization; + +import com.fasterxml.jackson.annotation.ObjectIdGenerator; +import com.fasterxml.jackson.annotation.ObjectIdResolver; +import org.libreccm.cdi.utils.CdiUtil; + +import java.io.Serializable; + +/** + * + * @author Jens Pelzetter + */ +public class CategorizationIdResolver implements ObjectIdResolver, Serializable{ + + private static final long serialVersionUID = 1L; + + @Override + public void bindItem( + final ObjectIdGenerator.IdKey id, final Object object + ) { + // According to the Jackson JavaDoc, this method can be used to keep + // track of objects directly in a resolver implementation. We don't need + // this here therefore this method is empty. + } + + @Override + public Object resolveId(final ObjectIdGenerator.IdKey id) { + return CdiUtil + .createCdiUtil() + .findBean(CategorizationRepository.class) + .findByUuid(id.key.toString()) + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "No Categorization with UUID %s in the database.", + id.key.toString() + ) + ) + ); + } + + @Override + public ObjectIdResolver newForDeserialization(final Object context) { + return new CategorizationIdResolver(); + } + + @Override + public boolean canUseFor(final ObjectIdResolver resolverType) { + return resolverType instanceof CategorizationIdResolver; + } +} diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategorizationRepository.java b/ccm-core/src/main/java/org/libreccm/categorization/CategorizationRepository.java new file mode 100644 index 000000000..0d59b8210 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/categorization/CategorizationRepository.java @@ -0,0 +1,54 @@ +package org.libreccm.categorization; + +import org.libreccm.core.AbstractEntityRepository; + +import java.util.Optional; + +import javax.persistence.NoResultException; + +/** + * + * @author Jens Pelzetter + */ +public class CategorizationRepository + extends AbstractEntityRepository { + + private static final long serialVersionUID = 1L; + + @Override + public Class getEntityClass() { + return Categorization.class; + } + + @Override + public String getIdAttributeName() { + return "categorizationId"; + } + + @Override + public Long getIdOfEntity(final Categorization entity) { + return entity.getCategorizationId(); + } + + @Override + public boolean isNew(final Categorization entity) { + return entity.getCategorizationId()== 0; + } + + public Optional findByUuid(final String uuid) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "Categorization.findByUuid", + Categorization.class + ) + .setParameter("uuid", uuid) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Category.java b/ccm-core/src/main/java/org/libreccm/categorization/Category.java index 7a54f2ed3..c1e59dc57 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/Category.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/Category.java @@ -138,7 +138,8 @@ import javax.validation.constraints.NotBlank; @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, resolver = CategoryIdResolver.class, - property = "uuid" + property = "uuid", + scope = Category.class ) public class Category extends CcmObject implements Serializable, Exportable { diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Domain.java b/ccm-core/src/main/java/org/libreccm/categorization/Domain.java index 505408780..c34626e7b 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/Domain.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/Domain.java @@ -133,9 +133,12 @@ import javax.validation.constraints.NotBlank; ) }) @XmlRootElement(name = "domain", namespace = CAT_XML_NS) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = DomainIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = DomainIdResolver.class, + property = "uuid", + scope = Domain.class +) public class Domain extends CcmObject implements Serializable, Exportable { private static final long serialVersionUID = 4012590760598188732L; diff --git a/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnership.java b/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnership.java index 09a77f170..c354a97c2 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnership.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnership.java @@ -68,8 +68,12 @@ import javax.xml.bind.annotation.XmlElement; query = "SELECT o FROM DomainOwnership o " + "WHERE o.owner = :owner AND o.domain = :domain") }) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + property = "uuid", + resolver = DomainOwnershipIdResolver.class, + scope = DomainOwnership.class +) public class DomainOwnership implements Serializable, Exportable { private static final long serialVersionUID = 201504301305L; diff --git a/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnershipIdResolver.java b/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnershipIdResolver.java new file mode 100644 index 000000000..c45bf8878 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnershipIdResolver.java @@ -0,0 +1,51 @@ +package org.libreccm.categorization; + +import com.fasterxml.jackson.annotation.ObjectIdGenerator; +import com.fasterxml.jackson.annotation.ObjectIdResolver; +import org.libreccm.cdi.utils.CdiUtil; + +import java.io.Serializable; + +/** + * + * @author Jens Pelzetter + */ +public class DomainOwnershipIdResolver implements ObjectIdResolver, Serializable{ + + private static final long serialVersionUID = 1L; + + @Override + public void bindItem( + final ObjectIdGenerator.IdKey id, final Object object + ) { + // According to the Jackson JavaDoc, this method can be used to keep + // track of objects directly in a resolver implementation. We don't need + // this here therefore this method is empty. + } + + @Override + public Object resolveId(final ObjectIdGenerator.IdKey id) { + return CdiUtil + .createCdiUtil() + .findBean(DomainOwnershipRepository.class) + .findByUuid(id.key.toString()) + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "No DomainOwnership with UUID %s in the database.", + id.key.toString() + ) + ) + ); + } + + @Override + public ObjectIdResolver newForDeserialization(final Object context) { + return new DomainOwnershipIdResolver(); + } + + @Override + public boolean canUseFor(final ObjectIdResolver resolverType) { + return resolverType instanceof DomainOwnershipIdResolver; + } +} diff --git a/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnershipRepository.java b/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnershipRepository.java new file mode 100644 index 000000000..6c59e22fd --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/categorization/DomainOwnershipRepository.java @@ -0,0 +1,54 @@ +package org.libreccm.categorization; + +import org.libreccm.core.AbstractEntityRepository; + +import java.util.Optional; + +import javax.persistence.NoResultException; + +/** + * + * @author Jens Pelzetter + */ +public class DomainOwnershipRepository + extends AbstractEntityRepository { + + private static final long serialVersionUID = 1L; + + @Override + public Class getEntityClass() { + return DomainOwnership.class; + } + + @Override + public String getIdAttributeName() { + return "ownershipId"; + } + + @Override + public Long getIdOfEntity(final DomainOwnership entity) { + return entity.getOwnershipId(); + } + + @Override + public boolean isNew(final DomainOwnership entity) { + return entity.getOwnershipId()== 0; + } + + public Optional findByUuid(final String uuid) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "DomainOwnership.findByUuid", + DomainOwnership.class + ) + .setParameter("uuid", uuid) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/core/CcmObject.java b/ccm-core/src/main/java/org/libreccm/core/CcmObject.java index b09c69642..175fa482f 100644 --- a/ccm-core/src/main/java/org/libreccm/core/CcmObject.java +++ b/ccm-core/src/main/java/org/libreccm/core/CcmObject.java @@ -90,9 +90,12 @@ import javax.persistence.Table; //persistence system we can't yet refactor it to make PMD happy. Also I think //this is a false warning. @SuppressWarnings("PMD.TooManyMethods") -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = CcmObjectIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = CcmObjectIdResolver.class, + property = "uuid", + scope = CcmObject.class +) public class CcmObject implements Exportable, Identifiable, Serializable { private static final long serialVersionUID = 201504261329L; @@ -115,7 +118,7 @@ public class CcmObject implements Exportable, Identifiable, Serializable { @Field @XmlElement(name = "uuid") private String uuid; - + /** * A human readable name identifying this {@code CcmObject} */ @@ -160,12 +163,12 @@ public class CcmObject implements Exportable, Identifiable, Serializable { public void setObjectId(final long objectId) { this.objectId = objectId; } - + @Override public String getUuid() { return uuid; } - + public void setUuid(final String uuid) { this.uuid = uuid; } diff --git a/ccm-core/src/main/java/org/libreccm/core/Resource.java b/ccm-core/src/main/java/org/libreccm/core/Resource.java index b3ae044e5..4085ccac8 100644 --- a/ccm-core/src/main/java/org/libreccm/core/Resource.java +++ b/ccm-core/src/main/java/org/libreccm/core/Resource.java @@ -69,12 +69,14 @@ import javax.persistence.TemporalType; @Entity @Table(name = "RESOURCES", schema = DB_SCHEMA) @NamedQueries({ - @NamedQuery(name = "Resource.findByUuid", - query = "SELECT r FROM Resource r WHERE r.uuid = :uuid"), -}) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = ResourceIdResolver.class, - property = "uuid") + @NamedQuery(name = "Resource.findByUuid", + query = "SELECT r FROM Resource r WHERE r.uuid = :uuid"),}) +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = ResourceIdResolver.class, + property = "uuid", + scope = Resource.class +) public class Resource extends CcmObject implements Serializable, Exportable { private static final long serialVersionUID = 7345482620613842781L; @@ -106,7 +108,7 @@ public class Resource extends CcmObject implements Serializable, Exportable { @ManyToOne @JsonIdentityReference(alwaysAsId = true) private ResourceType resourceType; - + /** * Date on which the resource was created. */ @@ -134,7 +136,7 @@ public class Resource extends CcmObject implements Serializable, Exportable { description = new LocalizedString(); childs = new ArrayList<>(); } - + public LocalizedString getTitle() { return title; } @@ -156,11 +158,11 @@ public class Resource extends CcmObject implements Serializable, Exportable { public ResourceType getResourceType() { return resourceType; } - + protected void setResourceType(final ResourceType resourceType) { this.resourceType = resourceType; } - + public Date getCreated() { if (created == null) { return null; @@ -219,11 +221,11 @@ public class Resource extends CcmObject implements Serializable, Exportable { if (obj == null) { return false; } - + if (!super.equals(obj)) { return false; } - + if (!(obj instanceof Resource)) { return false; } diff --git a/ccm-core/src/main/java/org/libreccm/core/ResourceType.java b/ccm-core/src/main/java/org/libreccm/core/ResourceType.java index 3e7160c96..6583eb4a7 100644 --- a/ccm-core/src/main/java/org/libreccm/core/ResourceType.java +++ b/ccm-core/src/main/java/org/libreccm/core/ResourceType.java @@ -60,14 +60,16 @@ import javax.persistence.Table; @Inheritance(strategy = InheritanceType.JOINED) @NamedQueries({ @NamedQuery(name = "ResourceType.findByUuid", - query = "SELECT r FROM ResourceType r WHERE r.uuid = :uuid") - , - @NamedQuery(name = "ResourceType.findByTitle", + query = "SELECT r FROM ResourceType r WHERE r.uuid = :uuid"), + @NamedQuery(name = "ResourceType.findByTitle", query = "SELECT r FROM ResourceType r WHERE r.title = :title") }) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = ResourceTypeIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = ResourceTypeIdResolver.class, + property = "uuid", + scope = ResourceType.class +) @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.StdCyclomaticComplexity", "PMD.ModifiedCyclomaticComplexity", diff --git a/ccm-core/src/main/java/org/libreccm/security/Group.java b/ccm-core/src/main/java/org/libreccm/security/Group.java index 242da61c7..3e620ee40 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Group.java +++ b/ccm-core/src/main/java/org/libreccm/security/Group.java @@ -66,18 +66,15 @@ import javax.persistence.Table; @NamedQuery( name = "Group.findByName", query = "SELECT g FROM Group g WHERE g.name = :name " - + "ORDER BY g.name") - , + + "ORDER BY g.name"), @NamedQuery( name = "Group.searchByName", query = "SELECT g FROM Group g " + "WHERE LOWER(g.name) LIKE CONCAT(LOWER(:name), '%') " - + "ORDER BY g.name") - , + + "ORDER BY g.name"), @NamedQuery( name = "Group.findAllOrderedByGroupName", - query = "SELECT g FROM Group g ORDER BY g.name") - , + query = "SELECT g FROM Group g ORDER BY g.name"), @NamedQuery( name = "Group.findByMember", query = "SELECT g FROM Group g " @@ -89,8 +86,7 @@ import javax.persistence.Table; @NamedEntityGraph( name = "Group.withMembersAndRoleMemberships", attributeNodes = { - @NamedAttributeNode(value = "memberships") - , + @NamedAttributeNode(value = "memberships"), @NamedAttributeNode(value = "roleMemberships", subgraph = "role")}, subgraphs = { @@ -99,8 +95,7 @@ import javax.persistence.Table; attributeNodes = { @NamedAttributeNode(value = "role", subgraph = "permissions") - }) - , + }), @NamedSubgraph( name = "permissions", attributeNodes = { @@ -108,9 +103,12 @@ import javax.persistence.Table; }) }) @XmlRootElement(name = "user-group", namespace = CORE_XML_NS) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = GroupIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = GroupIdResolver.class, + property = "uuid", + scope = Group.class +) public class Group extends Party implements Serializable, Exportable { private static final long serialVersionUID = -4800759206452780739L; @@ -177,4 +175,4 @@ public class Group extends Party implements Serializable, Exportable { return super.hashCode(); } -} \ No newline at end of file +} diff --git a/ccm-core/src/main/java/org/libreccm/security/GroupMembership.java b/ccm-core/src/main/java/org/libreccm/security/GroupMembership.java index 580713cd6..b6aea6289 100644 --- a/ccm-core/src/main/java/org/libreccm/security/GroupMembership.java +++ b/ccm-core/src/main/java/org/libreccm/security/GroupMembership.java @@ -73,7 +73,9 @@ import javax.persistence.Table; @XmlRootElement(name = "group-membership", namespace = CORE_XML_NS) @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, - property = "uuid" + property = "uuid", + resolver = GroupMembershipIdResolver.class, + scope = GroupMembership.class ) public class GroupMembership implements Serializable, Exportable { diff --git a/ccm-core/src/main/java/org/libreccm/security/GroupMembershipIdResolver.java b/ccm-core/src/main/java/org/libreccm/security/GroupMembershipIdResolver.java new file mode 100644 index 000000000..747090ede --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/security/GroupMembershipIdResolver.java @@ -0,0 +1,51 @@ +package org.libreccm.security; + +import com.fasterxml.jackson.annotation.ObjectIdGenerator; +import com.fasterxml.jackson.annotation.ObjectIdResolver; +import org.libreccm.cdi.utils.CdiUtil; + +import java.io.Serializable; + +/** + * + * @author Jens Pelzetter + */ +public class GroupMembershipIdResolver implements ObjectIdResolver, Serializable{ + + private static final long serialVersionUID = 1L; + + @Override + public void bindItem( + final ObjectIdGenerator.IdKey id, final Object object + ) { + // According to the Jackson JavaDoc, this method can be used to keep + // track of objects directly in a resolver implementation. We don't need + // this here therefore this method is empty. + } + + @Override + public Object resolveId(final ObjectIdGenerator.IdKey id) { + return CdiUtil + .createCdiUtil() + .findBean(GroupMembershipRepository.class) + .findByUuid(id.key.toString()) + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "No GroupMembership with UUID %s in the database.", + id.key.toString() + ) + ) + ); + } + + @Override + public ObjectIdResolver newForDeserialization(final Object context) { + return new GroupMembershipIdResolver(); + } + + @Override + public boolean canUseFor(final ObjectIdResolver resolverType) { + return resolverType instanceof GroupMembershipIdResolver; + } +} diff --git a/ccm-core/src/main/java/org/libreccm/security/GroupMembershipRepository.java b/ccm-core/src/main/java/org/libreccm/security/GroupMembershipRepository.java new file mode 100644 index 000000000..711152a24 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/security/GroupMembershipRepository.java @@ -0,0 +1,54 @@ +package org.libreccm.security; + +import org.libreccm.core.AbstractEntityRepository; + +import java.util.Optional; + +import javax.persistence.NoResultException; + +/** + * + * @author Jens Pelzetter + */ +public class GroupMembershipRepository + extends AbstractEntityRepository { + + private static final long serialVersionUID = 1L; + + @Override + public Class getEntityClass() { + return GroupMembership.class; + } + + @Override + public String getIdAttributeName() { + return "membershipId"; + } + + @Override + public Long getIdOfEntity(final GroupMembership entity) { + return entity.getMembershipId(); + } + + @Override + public boolean isNew(final GroupMembership entity) { + return entity.getMembershipId() == 0; + } + + public Optional findByUuid(final String uuid) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "GroupMembership.findByUuid", + GroupMembership.class + ) + .setParameter("uuid", uuid) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/security/Party.java b/ccm-core/src/main/java/org/libreccm/security/Party.java index a90081bcb..02c4f9aa3 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Party.java +++ b/ccm-core/src/main/java/org/libreccm/security/Party.java @@ -89,9 +89,12 @@ import javax.persistence.Table; attributeNodes = @NamedAttributeNode( value = "roleMemberships")) }) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = PartyIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = PartyIdResolver.class, + property = "uuid", + scope = Party.class +) public class Party implements Serializable { private static final long serialVersionUID = 3319997992281332204L; diff --git a/ccm-core/src/main/java/org/libreccm/security/Permission.java b/ccm-core/src/main/java/org/libreccm/security/Permission.java index a7be25110..942757e81 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Permission.java +++ b/ccm-core/src/main/java/org/libreccm/security/Permission.java @@ -105,9 +105,12 @@ import javax.persistence.TemporalType; }) @XmlRootElement(name = "permission", namespace = CORE_XML_NS) @XmlAccessorType(XmlAccessType.FIELD) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = PermissionIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = PermissionIdResolver.class, + property = "uuid", + scope = Permission.class +) public class Permission implements Serializable, Exportable { private static final long serialVersionUID = -5178045844045517958L; diff --git a/ccm-core/src/main/java/org/libreccm/security/Role.java b/ccm-core/src/main/java/org/libreccm/security/Role.java index 6771a57c4..0b800cfb8 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Role.java +++ b/ccm-core/src/main/java/org/libreccm/security/Role.java @@ -75,55 +75,45 @@ import javax.xml.bind.annotation.XmlRootElement; query = "SELECT r FROM Role r WHERE r.uuid = :uuid"), @NamedQuery(name = "Role.findByName", query = "SELECT r FROM Role r " - + "WHERE r.name = :name") - , + + "WHERE r.name = :name"), @NamedQuery( name = "Role.count", - query = "SELECT COUNT(r) FROM Role r") - , + query = "SELECT COUNT(r) FROM Role r"), @NamedQuery( name = "Role.findAllOrderedByRoleName", - query = "SELECT r FROM Role r ORDER BY r.name") - , + query = "SELECT r FROM Role r ORDER BY r.name"), @NamedQuery( name = "Role.findAllOrderedByRoleNameLimit", - query = "SELECT r FROM Role r ORDER BY r.name ") - , + query = "SELECT r FROM Role r ORDER BY r.name "), @NamedQuery( name = "Role.findAllOrderedByRoleNameDesc", - query = "SELECT r FROM Role r ORDER BY r.name DESC") - , + query = "SELECT r FROM Role r ORDER BY r.name DESC"), @NamedQuery( name = "Role.searchByName", query = "SELECT r FROM Role r " + "WHERE LOWER(r.name) LIKE CONCAT(LOWER(:name), '%') " - + "ORDER BY r.name ") - , + + "ORDER BY r.name "), @NamedQuery( name = "Role.searchByNameCount", query = "SELECT COUNT(r.name) FROM Role r " + "WHERE LOWER(r.name) LIKE CONCAT(LOWER(:name), '%') " + "GROUP BY r.name " - + "ORDER BY r.name ") - , + + "ORDER BY r.name "), @NamedQuery( name = "Role.findByPrivilege", query = "SELECT r FROM Role r JOIN r.permissions p " + "WHERE p.grantedPrivilege = :privilege " - + "ORDER BY r.name") - , + + "ORDER BY r.name"), @NamedQuery( name = "Role.findByPrivilegeAndObject", query = "SELECT r FROM Role r JOIN r.permissions p " + "WHERE p.grantedPrivilege = :privilege " + "AND p.object = :object " - + "ORDER BY r.name") - , + + "ORDER BY r.name"), @NamedQuery( name = "Role.findRolesOfUser", query = "SELECT r.role FROM RoleMembership r " - + "WHERE r.member = :user") - , + + "WHERE r.member = :user"), @NamedQuery( name = "Role.findByParty", query = "SELECT r FROM Role r " @@ -135,8 +125,7 @@ import javax.xml.bind.annotation.XmlRootElement; @NamedEntityGraph( name = Role.ENTITY_GRPAH_WITH_MEMBERS, attributeNodes = { - @NamedAttributeNode(value = "memberships"),}) - , + @NamedAttributeNode(value = "memberships"),}), @NamedEntityGraph( name = Role.ENTITY_GRPAH_WITH_PERMISSIONS, attributeNodes = { @@ -146,17 +135,21 @@ import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "role", namespace = CORE_XML_NS) @XmlAccessorType(XmlAccessType.FIELD) @SuppressWarnings({"PMD.ShortClassName", "PMD.TooManyMethods"}) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = RoleIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = RoleIdResolver.class, + property = "uuid", + scope = Role.class +) public class Role implements Serializable, Exportable { private static final long serialVersionUID = -7121296514181469687L; public static final String ENTITY_GRPAH_WITH_MEMBERS - = "Role.withMembers"; + = "Role.withMembers"; + public static final String ENTITY_GRPAH_WITH_PERMISSIONS - = "Role.withPermissions"; + = "Role.withPermissions"; @Id @Column(name = "ROLE_ID") @@ -167,7 +160,7 @@ public class Role implements Serializable, Exportable { @Column(name = "UUID", unique = true, nullable = false) @XmlElement(name = "uuid", namespace = CORE_XML_NS) private String uuid; - + /** * The name of the role. May only contain the letters a to z, A to Z, the * numbers 0 to 9, the {@code -} (dash) and the {@code _} (underscore). @@ -227,12 +220,12 @@ public class Role implements Serializable, Exportable { protected void setRoleId(final long roleId) { this.roleId = roleId; } - + @Override public String getUuid() { return uuid; } - + public void setUuid(final String uuid) { this.uuid = uuid; } diff --git a/ccm-core/src/main/java/org/libreccm/security/RoleMembership.java b/ccm-core/src/main/java/org/libreccm/security/RoleMembership.java index af8c01d28..d15a14a58 100644 --- a/ccm-core/src/main/java/org/libreccm/security/RoleMembership.java +++ b/ccm-core/src/main/java/org/libreccm/security/RoleMembership.java @@ -72,8 +72,12 @@ import javax.persistence.Table; ) }) @XmlRootElement(name = "role-membership", namespace = CORE_XML_NS) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + property = "uuid", + resolver = RoleMembershipIdResolver.class, + scope = RoleMembership.class +) public class RoleMembership implements Serializable, Exportable { private static final long serialVersionUID = -3049727720697964793L; diff --git a/ccm-core/src/main/java/org/libreccm/security/RoleMembershipIdResolver.java b/ccm-core/src/main/java/org/libreccm/security/RoleMembershipIdResolver.java new file mode 100644 index 000000000..a1549eba6 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/security/RoleMembershipIdResolver.java @@ -0,0 +1,51 @@ +package org.libreccm.security; + +import com.fasterxml.jackson.annotation.ObjectIdGenerator; +import com.fasterxml.jackson.annotation.ObjectIdResolver; +import org.libreccm.cdi.utils.CdiUtil; + +import java.io.Serializable; + +/** + * + * @author Jens Pelzetter + */ +public class RoleMembershipIdResolver implements ObjectIdResolver, Serializable{ + + private static final long serialVersionUID = 1L; + + @Override + public void bindItem( + final ObjectIdGenerator.IdKey id, final Object object + ) { + // According to the Jackson JavaDoc, this method can be used to keep + // track of objects directly in a resolver implementation. We don't need + // this here therefore this method is empty. + } + + @Override + public Object resolveId(final ObjectIdGenerator.IdKey id) { + return CdiUtil + .createCdiUtil() + .findBean(RoleMembershipRepository.class) + .findByUuid(id.key.toString()) + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "No RoleMembership with UUID %s in the database.", + id.key.toString() + ) + ) + ); + } + + @Override + public ObjectIdResolver newForDeserialization(final Object context) { + return new RoleMembershipIdResolver(); + } + + @Override + public boolean canUseFor(final ObjectIdResolver resolverType) { + return resolverType instanceof RoleMembershipIdResolver; + } +} diff --git a/ccm-core/src/main/java/org/libreccm/security/RoleMembershipRepository.java b/ccm-core/src/main/java/org/libreccm/security/RoleMembershipRepository.java new file mode 100644 index 000000000..265b836e1 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/security/RoleMembershipRepository.java @@ -0,0 +1,52 @@ +package org.libreccm.security; + +import org.libreccm.core.AbstractEntityRepository; + +import java.util.Optional; + +import javax.persistence.NoResultException; + +/** + * + * @author Jens Pelzetter + */ +public class RoleMembershipRepository + extends AbstractEntityRepository { + + @Override + public Class getEntityClass() { + return RoleMembership.class; + } + + @Override + public String getIdAttributeName() { + return "membershipId"; + } + + @Override + public Long getIdOfEntity(final RoleMembership entity) { + return entity.getMembershipId(); + } + + @Override + public boolean isNew(final RoleMembership entity) { + return entity.getMembershipId() == 0; + } + + public Optional findByUuid(final String uuid) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "RoleMembership.findByUuid", + RoleMembership.class + ) + .setParameter("uuid", uuid) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/security/User.java b/ccm-core/src/main/java/org/libreccm/security/User.java index 56f4857e2..5ec86486a 100644 --- a/ccm-core/src/main/java/org/libreccm/security/User.java +++ b/ccm-core/src/main/java/org/libreccm/security/User.java @@ -147,9 +147,12 @@ import javax.xml.bind.annotation.XmlTransient; //Supressing a few warnings from PMD because they misleading here. //User is perfectly fine class name, and the complexity is not to high... @SuppressWarnings({"PMD.ShortClassName", "PMD.LongVariable"}) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = UserIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = UserIdResolver.class, + property = "uuid", + scope = User.class +) public class User extends Party implements Serializable, Exportable { private static final long serialVersionUID = 4035223413596611393L; diff --git a/ccm-core/src/main/java/org/libreccm/web/CcmApplication.java b/ccm-core/src/main/java/org/libreccm/web/CcmApplication.java index 0f2a45287..362f7409b 100644 --- a/ccm-core/src/main/java/org/libreccm/web/CcmApplication.java +++ b/ccm-core/src/main/java/org/libreccm/web/CcmApplication.java @@ -54,7 +54,7 @@ import javax.persistence.Table; /** * Base class for CCM application - * + * * @author Jens Pelzetter */ @Entity @@ -78,10 +78,13 @@ import javax.persistence.Table; }) }) @XmlRootElement(name = "application", namespace = WEB_XML_NS) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = ApplicationIdResolver.class, - property = "uuid") -public class CcmApplication extends Resource implements Serializable, +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = ApplicationIdResolver.class, + property = "uuid", + scope = CcmApplication.class +) +public class CcmApplication extends Resource implements Serializable, Exportable { private static final long serialVersionUID = 9205226362368890784L; diff --git a/ccm-core/src/main/java/org/libreccm/workflow/AssignableTask.java b/ccm-core/src/main/java/org/libreccm/workflow/AssignableTask.java index 1c7e46703..55436c195 100644 --- a/ccm-core/src/main/java/org/libreccm/workflow/AssignableTask.java +++ b/ccm-core/src/main/java/org/libreccm/workflow/AssignableTask.java @@ -59,27 +59,23 @@ import javax.persistence.TemporalType; @NamedQueries({ @NamedQuery( name = "AssignableTask.findByUuid", - query = "SELECT t FROM AssignableTask t WHERE t.uuid = :uuid") - , + query = "SELECT t FROM AssignableTask t WHERE t.uuid = :uuid"), @NamedQuery( name = "AssignableTask.findLockedBy", - query = "SELECT t FROM AssignableTask t WHERE t.lockingUser = :user") - , + query = "SELECT t FROM AssignableTask t WHERE t.lockingUser = :user"), @NamedQuery( name = "AssignableTask.findEnabledTasksForWorkflow", query = "SELECT t FROM AssignableTask t " + "WHERE t.lockingUser = :user " + "AND t.workflow = :workflow" - ) - , + ), @NamedQuery( name = "AssignableTask.findAssignedTasks", query = "SELECT DISTINCT t FROM AssignableTask t " + "JOIN t.assignments a " + "WHERE a.role IN :roles " + "AND t.workflow = :workflow " - + "AND t.active = true") - , + + "AND t.active = true"), @NamedQuery( name = "AssignableTask.isAssignedTo", query = "SELECT (CASE WHEN COUNT(t) > 0 THEN true ELSE false END) " @@ -87,8 +83,7 @@ import javax.persistence.TemporalType; + "JOIN t.assignments a " + "WHERE a.role IN :roles " + "AND t = :task" - ) - , + ), @NamedQuery( name = "AssignableTask.findOverdueTasks", query = "SELECT t FROM AssignableTask t " @@ -99,9 +94,12 @@ import javax.persistence.TemporalType; @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.StdCyclomaticComplexity", "PMD.ModifiedCyclomaticComplexity"}) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = AssignableTaskIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = AssignableTaskIdResolver.class, + property = "uuid", + scope = AssignableTask.class +) public class AssignableTask extends Task implements Serializable, Exportable { private static final long serialVersionUID = 4188064584389893019L; diff --git a/ccm-core/src/main/java/org/libreccm/workflow/Task.java b/ccm-core/src/main/java/org/libreccm/workflow/Task.java index edf674783..6e1f778ff 100644 --- a/ccm-core/src/main/java/org/libreccm/workflow/Task.java +++ b/ccm-core/src/main/java/org/libreccm/workflow/Task.java @@ -77,44 +77,38 @@ import javax.xml.bind.annotation.XmlElementWrapper; @NamedQueries({ @NamedQuery( name = "Task.findByUuid", - query = "SELECT t FROM Task t WHERE t.uuid = :uuid") - , + query = "SELECT t FROM Task t WHERE t.uuid = :uuid"), @NamedQuery( name = "Task.countUnfinishedAndActiveTasksForWorkflow", query = "SELECT COUNT(t) FROM Task t " + "WHERE t.taskState != org.libreccm.workflow.TaskState.FINISHED " + "AND t.active = true " - + "AND t.workflow = :workflow") - , + + "AND t.workflow = :workflow"), @NamedQuery( name = "Task.countUnfinishedTasksForWorkflow", query = "SELECT COUNT(t) FROM Task t " + "WHERE t.taskState != org.libreccm.workflow.TaskState.FINISHED " + "AND t.workflow = :workflow" - ) - , + ), @NamedQuery( name = "Task.findEnabledTasks", query = "SELECT t FROM Task t " + "WHERE t.workflow = :workflow " + "AND t.taskState = org.libreccm.workflow.TaskState.ENABLED " + "AND t.active = true" - ) - , + ), @NamedQuery( name = "Task.findFinishedTasks", query = "SELECT t FROM Task t " + "WHERE t.workflow = :workflow " - + "AND t.taskState = org.libreccm.workflow.TaskState.FINISHED") - , + + "AND t.taskState = org.libreccm.workflow.TaskState.FINISHED"), @NamedQuery( name = "Task.existsDependency", query = "SELECT (CASE WHEN COUNT(d) > 0 THEN true ELSE false END) " + "FROM TaskDependency d " + "WHERE d.blockedTask = :blockedTask " + "AND d.blockingTask = :blockingTask" - ) - , + ), @NamedQuery( name = "Task.findDependency", query = "SELECT d FROM TaskDependency d " @@ -122,9 +116,12 @@ import javax.xml.bind.annotation.XmlElementWrapper; + "AND d.blockingTask = :blockingTask" ) }) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = TaskIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = TaskIdResolver.class, + property = "uuid", + scope = Task.class +) public class Task implements Identifiable, Serializable { private static final long serialVersionUID = 8161343036908150426L; @@ -207,7 +204,6 @@ public class Task implements Identifiable, Serializable { @JsonIgnore private List blockingTasks; - /** * Comments for the task. */ diff --git a/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignment.java b/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignment.java index 16cb3f651..08e2223be 100644 --- a/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignment.java +++ b/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignment.java @@ -68,7 +68,8 @@ import javax.persistence.Table; }) @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, - property = "customAssignId" + resolver = TaskAssignmentIdResolver.class, + property = "uuid" ) public class TaskAssignment implements Serializable, Exportable { diff --git a/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignmentIdResolver.java b/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignmentIdResolver.java new file mode 100644 index 000000000..201cb91b6 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignmentIdResolver.java @@ -0,0 +1,50 @@ +package org.libreccm.workflow; + +import com.fasterxml.jackson.annotation.ObjectIdGenerator; +import com.fasterxml.jackson.annotation.ObjectIdResolver; +import org.libreccm.cdi.utils.CdiUtil; + +import java.io.Serializable; + +/** + * + * @author Jens Pelzetter + */ +public class TaskAssignmentIdResolver implements ObjectIdResolver, Serializable{ + + private static final long serialVersionUID = 1L; + + @Override + public void bindItem(final ObjectIdGenerator.IdKey id, final Object pojo) { + // According to the Jackson JavaDoc, this method can be used to keep + // track of objects directly in a resolver implementation. We don't need + // this here therefore this method is empty. + } + + @Override + public Object resolveId(final ObjectIdGenerator.IdKey id) { +return CdiUtil + .createCdiUtil() + .findBean(TaskAssignmentRepository.class) + .findByUuid(id.key.toString()) + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "No TaskAssignment with UUID %s found in the database.", + id.key.toString() + ) + ) + ); + } + + @Override + public ObjectIdResolver newForDeserialization(final Object context) { + return new TaskAssignmentIdResolver(); + } + + @Override + public boolean canUseFor(final ObjectIdResolver resolverType) { + return resolverType instanceof TaskAssignmentIdResolver; + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignmentRepository.java b/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignmentRepository.java new file mode 100644 index 000000000..2a2d53546 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/workflow/TaskAssignmentRepository.java @@ -0,0 +1,59 @@ +package org.libreccm.workflow; + +import org.libreccm.core.AbstractEntityRepository; + +import java.util.Optional; + +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; + +/** + * + * @author Jens Pelzetter + */ +public class TaskAssignmentRepository + extends AbstractEntityRepository { + + private static final long serialVersionUID = 1L; + + @Override + public Class getEntityClass() { + return TaskAssignment.class; + } + + @Override + public String getIdAttributeName() { + return "taskAssignmentId"; + } + + @Override + public Long getIdOfEntity(final TaskAssignment entity) { + return entity.getTaskAssignmentId(); + } + + @Override + public boolean isNew(final TaskAssignment entity) { + return entity.getTaskAssignmentId() == 0; + } + + public Optional findByUuid(final String uuid) { + final TypedQuery query = getEntityManager() + .createNamedQuery("TaskComment.findByUuid", TaskComment.class); + query.setParameter("uuid", uuid); + + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "TaskAssignment.findByUuid", + TaskAssignment.class + ) + .setParameter("uuid", uuid) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/workflow/TaskComment.java b/ccm-core/src/main/java/org/libreccm/workflow/TaskComment.java index 156554794..efec8e9cc 100644 --- a/ccm-core/src/main/java/org/libreccm/workflow/TaskComment.java +++ b/ccm-core/src/main/java/org/libreccm/workflow/TaskComment.java @@ -54,13 +54,16 @@ import javax.persistence.Table; @Entity @Table(name = "WORKFLOW_TASK_COMMENTS", schema = CoreConstants.DB_SCHEMA) @NamedQueries({ - @NamedQuery( - name = "TaskComment.findByUuid", - query = "SELECT c FROM TaskComment c WHERE c.uuid = :uuid") + @NamedQuery( + name = "TaskComment.findByUuid", + query = "SELECT c FROM TaskComment c WHERE c.uuid = :uuid") }) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = TaskCommentIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = TaskCommentIdResolver.class, + property = "uuid", + scope = TaskComment.class +) public class TaskComment implements Identifiable, Serializable, Exportable { private static final long serialVersionUID = 3842991529698351698L; @@ -179,11 +182,11 @@ public class TaskComment implements Identifiable, Serializable, Exportable { public String toString(final String data) { return String.format("%s{ " - + "commentId = %d, " - + "uuid = \"%s\"" - + "comment = \"%s\", " - + "author = %s%s" - + " }", + + "commentId = %d, " + + "uuid = \"%s\"" + + "comment = \"%s\", " + + "author = %s%s" + + " }", super.toString(), commentId, uuid, diff --git a/ccm-core/src/main/java/org/libreccm/workflow/TaskDependency.java b/ccm-core/src/main/java/org/libreccm/workflow/TaskDependency.java index f5ac216b2..ca6625cc8 100644 --- a/ccm-core/src/main/java/org/libreccm/workflow/TaskDependency.java +++ b/ccm-core/src/main/java/org/libreccm/workflow/TaskDependency.java @@ -48,7 +48,8 @@ import javax.persistence.Table; @NamedQueries({ @NamedQuery( name = "TaskDependency.findById", - query = "SELECT d FROM TaskDependency d WHERE d.taskDependencyId = :dependencyId" + query + = "SELECT d FROM TaskDependency d WHERE d.taskDependencyId = :dependencyId" ), @NamedQuery( name = "TaskDependency.findByUuid", @@ -65,7 +66,8 @@ import javax.persistence.Table; }) @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, - property = "uuid" + resolver = TaskDependencyIdResolver.class, + property = "uuid" ) public class TaskDependency implements Serializable, Exportable { diff --git a/ccm-core/src/main/java/org/libreccm/workflow/TaskDependencyIdResolver.java b/ccm-core/src/main/java/org/libreccm/workflow/TaskDependencyIdResolver.java new file mode 100644 index 000000000..c5499dfd2 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/workflow/TaskDependencyIdResolver.java @@ -0,0 +1,51 @@ +package org.libreccm.workflow; + +import com.fasterxml.jackson.annotation.ObjectIdGenerator; +import com.fasterxml.jackson.annotation.ObjectIdResolver; +import org.libreccm.cdi.utils.CdiUtil; + +import java.io.Serializable; + +/** + * + * @author Jens Pelzetter + */ +public class TaskDependencyIdResolver + implements ObjectIdResolver, Serializable { + + private static final long serialVersionUID = 1L; + + @Override + public void bindItem(final ObjectIdGenerator.IdKey id, final Object pojo) { + // According to the Jackson JavaDoc, this method can be used to keep + // track of objects directly in a resolver implementation. We don't need + // this here therefore this method is empty. + } + + @Override + public Object resolveId(final ObjectIdGenerator.IdKey id) { + return CdiUtil + .createCdiUtil() + .findBean(TaskDependencyRepository.class) + .findByUuid(id.key.toString()) + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "No TaskDependency with UUID %s found in the database.", + id.key.toString() + ) + ) + ); + } + + @Override + public ObjectIdResolver newForDeserialization(final Object context) { + return new TaskDependencyIdResolver(); + } + + @Override + public boolean canUseFor(final ObjectIdResolver resolverType) { + return resolverType instanceof TaskDependencyIdResolver; + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/workflow/TaskDependencyRepository.java b/ccm-core/src/main/java/org/libreccm/workflow/TaskDependencyRepository.java new file mode 100644 index 000000000..45cf643df --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/workflow/TaskDependencyRepository.java @@ -0,0 +1,65 @@ +package org.libreccm.workflow; + +import org.libreccm.core.AbstractEntityRepository; + +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; + +/** + * Repository for {@link TaskDependency}. + * + * @author Jens Pelzetter + */ +@RequestScoped +public class TaskDependencyRepository + extends AbstractEntityRepository { + + private static final long serialVersionUID = 1L; + + @Override + public Class getEntityClass() { + return TaskDependency.class; + } + + @Override + public String getIdAttributeName() { + return "taskDependencyId"; + } + + @Override + public Long getIdOfEntity(final TaskDependency entity) { + return entity.getTaskDependencyId(); + } + + @Override + public boolean isNew(TaskDependency entity) { + return entity.getTaskDependencyId() == 0; + } + + /** + * Finds a {@link TaskComment} by its uuid. + * + * @param uuid The uuid of the item to find + * + * @return An optional either with the found item or empty + */ + public Optional findByUuid(final String uuid) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "TaskDependency.findByUuid", + TaskDependency.class + ) + .setParameter("uuid", uuid) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/workflow/Workflow.java b/ccm-core/src/main/java/org/libreccm/workflow/Workflow.java index 02f015a33..1cd6253d2 100644 --- a/ccm-core/src/main/java/org/libreccm/workflow/Workflow.java +++ b/ccm-core/src/main/java/org/libreccm/workflow/Workflow.java @@ -70,16 +70,18 @@ import org.libreccm.imexport.Exportable; @NamedQueries({ @NamedQuery( name = "Workflow.findByUuid", - query = "SELECT w FROM Workflow w WHERE w.uuid = :uuid") - , + query = "SELECT w FROM Workflow w WHERE w.uuid = :uuid"), @NamedQuery( name = "Workflow.findForObject", query = "SELECT w FROM Workflow w " + "WHERE w.object = :object") }) -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, - resolver = WorkflowIdResolver.class, - property = "uuid") +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = WorkflowIdResolver.class, + property = "uuid", + scope = Workflow.class +) public class Workflow implements Identifiable, Serializable, Exportable { private static final long serialVersionUID = 4322500264543325829L;