diff --git a/ccm-cms/package-lock.json b/ccm-cms/package-lock.json index d21cc6d98..000bed0bf 100644 --- a/ccm-cms/package-lock.json +++ b/ccm-cms/package-lock.json @@ -1,12 +1,12 @@ { "name": "@librecms/ccm-cms", - "version": "7.0.0-SNAPSHOT.2022-10-25T175437", + "version": "7.0.0-SNAPSHOT.2022-10-29T142641", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@librecms/ccm-cms", - "version": "7.0.0-SNAPSHOT.2022-10-25T175437", + "version": "7.0.0-SNAPSHOT.2022-10-29T142641", "license": "LGPL-3.0-or-later", "dependencies": { "@tiptap/core": "^2.0.0-beta.127", diff --git a/ccm-cms/package.json b/ccm-cms/package.json index 1371c7452..674361e73 100644 --- a/ccm-cms/package.json +++ b/ccm-cms/package.json @@ -1,6 +1,6 @@ { "name": "@librecms/ccm-cms", - "version": "7.0.0-SNAPSHOT.2022-10-25T175437", + "version": "7.0.0-SNAPSHOT.2022-10-29T142641", "description": "JavaScript stuff for ccm-cms", "main": "target/generated-resources/assets/@content-sections/cms-admin.js", "types": "target/generated-resources/assets/@content-sections/cms-admin.d.ts", 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 98027b179..766ab40a5 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleDefinition.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleDefinition.java @@ -19,6 +19,7 @@ package org.librecms.lifecycle; import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.JsonIdentityReference; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import org.hibernate.search.annotations.Field; import org.libreccm.core.Identifiable; @@ -107,6 +108,7 @@ public class LifecycleDefinition @OneToMany @JoinColumn(name = "LIFECYCLE_DEFINITION_ID") + @JsonIdentityReference(alwaysAsId = true) private List phaseDefinitions; public LifecycleDefinition() { 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 0bb915e8e..41dc90982 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinition.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinition.java @@ -32,7 +32,10 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; import javax.persistence.Table; +import javax.validation.constraints.NotNull; import static org.librecms.CmsConstants.*; @@ -42,6 +45,12 @@ import static org.librecms.CmsConstants.*; */ @Entity @Table(name = "LIFECYCLE_PHASE_DEFINITIONS", schema = DB_SCHEMA) +@NamedQueries({ + @NamedQuery( + name = "PhaseDefinition.findByUuid", + query = "SELECT FROM PhaseDefinition p WHERE p.uuid = :uuid" + ) +}) public class PhaseDefinition implements Serializable { private static final long serialVersionUID = -7718926310758794075L; @@ -51,24 +60,34 @@ public class PhaseDefinition implements Serializable { @Column(name = "PHASE_DEFINITION_ID") private long definitionId; + @Column(name = "uuid", unique = true, nullable = false) + @NotNull + private String uuid; + @Embedded @AssociationOverride( name = "values", - joinTable = @JoinTable(name = "LIFECYCLE_PHASE_DEFINITION_LABELS", - schema = DB_SCHEMA, - joinColumns = { - @JoinColumn(name = "OBJECT_ID")} - )) + joinTable = @JoinTable( + name = "LIFECYCLE_PHASE_DEFINITION_LABELS", + schema = DB_SCHEMA, + joinColumns = { + @JoinColumn(name = "OBJECT_ID") + } + ) + ) private LocalizedString label; @Embedded @AssociationOverride( name = "values", - joinTable = @JoinTable(name = "LIFECYCLE_PHASE_DEFINITION_DESCRIPTIONS", - schema = DB_SCHEMA, - joinColumns = { - @JoinColumn(name = "OBJECT_ID")} - )) + joinTable = @JoinTable( + name = "LIFECYCLE_PHASE_DEFINITION_DESCRIPTIONS", + schema = DB_SCHEMA, + joinColumns = { + @JoinColumn(name = "OBJECT_ID") + } + ) + ) private LocalizedString description; @Column(name = "DEFAULT_DELAY") @@ -84,15 +103,23 @@ public class PhaseDefinition implements Serializable { label = new LocalizedString(); description = new LocalizedString(); } - + public long getDefinitionId() { return definitionId; } - public void setDefinitionId(final long definitionId) { + protected void setDefinitionId(final long definitionId) { this.definitionId = definitionId; } + public String getUuid() { + return uuid; + } + + protected void setUuid(final String uuid) { + this.uuid = uuid; + } + public LocalizedString getLabel() { return label; } diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinitionIdResolver.java b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinitionIdResolver.java new file mode 100644 index 000000000..98e47e510 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinitionIdResolver.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.lifecycle; + +import com.fasterxml.jackson.annotation.ObjectIdGenerator; +import com.fasterxml.jackson.annotation.ObjectIdResolver; +import org.libreccm.cdi.utils.CdiUtil; + +import java.io.Serializable; + +import javax.enterprise.context.RequestScoped; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class PhaseDefinitionIdResolver + implements Serializable, ObjectIdResolver { + + @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(PhaseDefinititionRepository.class) + .findByUuid(id.key.toString()) + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "No PhaseDefinition with UUID %s in the database.", + id.key.toString() + ) + ) + ); + } + + @Override + public ObjectIdResolver newForDeserialization(final Object context) { + return new PhaseDefinitionIdResolver(); + } + + @Override + public boolean canUseFor(final ObjectIdResolver resolverType) { + return resolverType instanceof PhaseDefinitionIdResolver; + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinititionRepository.java b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinititionRepository.java index 50c9f34de..33e308d36 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinititionRepository.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinititionRepository.java @@ -20,7 +20,10 @@ package org.librecms.lifecycle; import org.libreccm.core.AbstractEntityRepository; +import java.util.Optional; + import javax.enterprise.context.RequestScoped; +import javax.persistence.NoResultException; /** * @@ -30,6 +33,8 @@ import javax.enterprise.context.RequestScoped; public class PhaseDefinititionRepository extends AbstractEntityRepository { + private static final long serialVersionUID = 1L; + @Override public Class getEntityClass() { return PhaseDefinition.class; @@ -50,4 +55,20 @@ public class PhaseDefinititionRepository return phaseDefinition.getDefinitionId() == 0; } + public Optional findByUuid(final String uuid) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "PhaseDefinition.findByUuid", + PhaseDefinition.class + ) + .setParameter("uuid", uuid) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + } diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_34__add_uuid_to_phase_definition.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_34__add_uuid_to_phase_definition.sql new file mode 100644 index 000000000..3129d7318 --- /dev/null +++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_34__add_uuid_to_phase_definition.sql @@ -0,0 +1,5 @@ +alter table CCM_CMS.LIFECYCLE_PHASE_DEFINITIONS add column UUID varchar(255); +update CCM_CMS.LIFECYCLE_PHASE_DEFINITIONS set UUID = random_uuid(); +alter table CCM_CMS.LIFECYCLE_PHASE_DEFINITIONS alter column UUID not null; +alter table CCM_CMS.LIFECYCLE_PHASE_DEFINITIONS + add constraint UK_tcvepjkkbcehplxddnil66fwn unique (uuid); diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_34__add_uuid_to_phase_definition.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_34__add_uuid_to_phase_definition.sql new file mode 100644 index 000000000..0cf5e84cf --- /dev/null +++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_34__add_uuid_to_phase_definition.sql @@ -0,0 +1,5 @@ +alter table CCM_CMS.LIFECYCLE_PHASE_DEFINITIONS add column UUID varchar(255); +update CCM_CMS.LIFECYCLE_PHASE_DEFINITIONS set UUID = gen_random_uuid(); +alter table CCM_CMS.LIFECYCLE_PHASE_DEFINITIONS alter column UUID set not null; +alter table CCM_CMS.LIFECYCLE_PHASE_DEFINITIONS + add constraint UK_tcvepjkkbcehplxddnil66fwn unique (uuid);