diff --git a/ccm-cms/package-lock.json b/ccm-cms/package-lock.json index 174578fe1..a86ac1a90 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-31T074006", + "version": "7.0.0-SNAPSHOT.2022-10-31T082859", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@librecms/ccm-cms", - "version": "7.0.0-SNAPSHOT.2022-10-31T074006", + "version": "7.0.0-SNAPSHOT.2022-10-31T082859", "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 f690dae5d..da60c7f81 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-31T074006", + "version": "7.0.0-SNAPSHOT.2022-10-31T082859", "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/Lifecycle.java b/ccm-cms/src/main/java/org/librecms/lifecycle/Lifecycle.java index 752b5c143..3a041f638 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/Lifecycle.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/Lifecycle.java @@ -109,6 +109,7 @@ public class Lifecycle implements Exportable, Identifiable, Serializable { private LifecycleDefinition definition; @OneToMany(mappedBy = "lifecycle") + @JsonIdentityReference(alwaysAsId = true) private List phases; public Lifecycle() { diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleImExporter.java b/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleImExporter.java index c296c770a..6d37889ab 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleImExporter.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/LifecycleImExporter.java @@ -49,9 +49,9 @@ public class LifecycleImExporter extends AbstractEntityImExporter { @Override protected Set> getRequiredEntities() { return Set.of( - LifecycleDefinition.class + LifecycleDefinition.class, + Phase.class ); -// return Collections.emptySet(); } @Override 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 dc4daa7cf..5a4f39b1f 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/Phase.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/Phase.java @@ -18,6 +18,10 @@ */ package org.librecms.lifecycle; +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import org.libreccm.imexport.Exportable; + import java.io.Serializable; import java.util.Date; import java.util.Objects; @@ -29,10 +33,13 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; import javax.persistence.OneToOne; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import javax.validation.constraints.NotNull; import static org.librecms.CmsConstants.*; @@ -42,7 +49,18 @@ import static org.librecms.CmsConstants.*; */ @Entity @Table(name = "LIFECYLE_PHASES", schema = DB_SCHEMA) -public class Phase implements Serializable { +@NamedQueries({ + @NamedQuery( + name = "Phase.findUuid", + query = "SELECT p FROM Phase p WHERE p.uuid = :uuid" + ) +}) +@JsonIdentityInfo( + generator = ObjectIdGenerators.PropertyGenerator.class, + resolver = PhaseIdResolver.class, + property = "uuid" +) +public class Phase implements Exportable, Serializable { private static final long serialVersionUID = -1683874069942019941L; @@ -51,6 +69,10 @@ public class Phase implements Serializable { @Column(name = "PHASE_ID") private long phaseId; + @Column(name = "uuid", unique = true, nullable = false) + @NotNull + private String uuid; + @Column(name = "START_DATE_TIME") @Temporal(TemporalType.DATE) private Date startDateTime; @@ -80,10 +102,19 @@ public class Phase implements Serializable { return phaseId; } - public void setPhaseId(final long phaseId) { + protected void setPhaseId(final long phaseId) { this.phaseId = phaseId; } + @Override + public String getUuid() { + return uuid; + } + + protected void setUuid(final String uuid) { + this.uuid = uuid; + } + public Date getStartDateTime() { if (startDateTime == null) { return null; diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinitionIdResolver.java b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinitionIdResolver.java index 98e47e510..3c4038a80 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinitionIdResolver.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinitionIdResolver.java @@ -34,6 +34,8 @@ import javax.enterprise.context.RequestScoped; public class PhaseDefinitionIdResolver implements Serializable, ObjectIdResolver { + private static final long serialVersionUID = 1L; + @Override public void bindItem( final ObjectIdGenerator.IdKey id, 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 33e308d36..312c11e98 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinititionRepository.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseDefinititionRepository.java @@ -21,6 +21,7 @@ package org.librecms.lifecycle; import org.libreccm.core.AbstractEntityRepository; import java.util.Optional; +import java.util.UUID; import javax.enterprise.context.RequestScoped; import javax.persistence.NoResultException; @@ -54,6 +55,12 @@ public class PhaseDefinititionRepository public boolean isNew(final PhaseDefinition phaseDefinition) { return phaseDefinition.getDefinitionId() == 0; } + + @Override + public void initNewEntity(final PhaseDefinition phaseDefinition) { + super.initNewEntity(phaseDefinition); + phaseDefinition.setUuid(UUID.randomUUID().toString()); + } public Optional findByUuid(final String uuid) { try { diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseIdResolver.java b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseIdResolver.java new file mode 100644 index 000000000..3382591c7 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseIdResolver.java @@ -0,0 +1,75 @@ +/* + * 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 PhaseIdResolver + implements Serializable, ObjectIdResolver { + + 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(PhaseRepository.class) + .findByUuid(id.key.toString()) + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "No Phase with UUID %s in the database.", + id.key.toString() + ) + ) + ); + } + + @Override + public ObjectIdResolver newForDeserialization(final Object context) { + return new PhaseIdResolver(); + } + + @Override + public boolean canUseFor(final ObjectIdResolver resolverType) { + return resolverType instanceof PhaseIdResolver; + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseImExporter.java b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseImExporter.java new file mode 100644 index 000000000..110b08842 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseImExporter.java @@ -0,0 +1,72 @@ +/* + * 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 org.libreccm.imexport.AbstractEntityImExporter; +import org.libreccm.imexport.Exportable; +import org.libreccm.imexport.Processes; + +import java.util.Collections; +import java.util.Objects; +import java.util.Set; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Processes(Phase.class) +public class PhaseImExporter + extends AbstractEntityImExporter { + + @Inject + private PhaseRepository phaseRepo; + + @Override + public Class getEntityClass() { + return Phase.class; + } + + @Override + protected Set> getRequiredEntities() { + return Collections.emptySet(); + } + + @Override + protected void saveImportedEntity(final Phase entity) { + phaseRepo.save(entity); + } + + @Override + protected Phase reloadEntity(final Phase entity) { + return phaseRepo + .findById(Objects.requireNonNull(entity).getPhaseId()) + .orElseThrow( + () -> new IllegalArgumentException( + String.format( + "Phase entity %s not found in database.", + Objects.toString(entity) + ) + ) + ); + } +} diff --git a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseRepository.java b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseRepository.java index c63f21d4c..12c24df7e 100644 --- a/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseRepository.java +++ b/ccm-cms/src/main/java/org/librecms/lifecycle/PhaseRepository.java @@ -20,7 +20,11 @@ package org.librecms.lifecycle; import org.libreccm.core.AbstractEntityRepository; +import java.util.Optional; +import java.util.UUID; + import javax.enterprise.context.RequestScoped; +import javax.persistence.NoResultException; /** * @@ -51,4 +55,23 @@ public class PhaseRepository extends AbstractEntityRepository { return phase.getPhaseId() == 0; } + @Override + public void initNewEntity(final Phase phase) { + super.initNewEntity(phase); + phase.setUuid(UUID.randomUUID().toString()); + } + + public Optional findByUuid(final String uuid) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery("Phase.findUuid", Phase.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_35__add_uuid_to_phase.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_35__add_uuid_to_phase.sql new file mode 100644 index 000000000..1eafa7c86 --- /dev/null +++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_35__add_uuid_to_phase.sql @@ -0,0 +1,6 @@ +alter table CCM_CMS.LIFECYCLE_PHASES add column UUID varchar(255); +update CCM_CMS.LIFECYCLE_PHASES set UUID = random_uuid(); +alter table CCM_CMS.LIFECYCLE_PHASES alter column UUID not null; +alter table CCM_CMS.LIFECYCLE_PHASES + add constraint UK_bkk376s9kchydlkuq052shnh5 unique (uuid); + diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_35__add_uuid_to_phase.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_35__add_uuid_to_phase.sql new file mode 100644 index 000000000..e8f82d1f4 --- /dev/null +++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_35__add_uuid_to_phase.sql @@ -0,0 +1,6 @@ +alter table CCM_CMS.LIFECYCLE_PHASES add column UUID varchar(255); +update CCM_CMS.LIFECYCLE_PHASES set UUID = gen_random_uuid(); +alter table CCM_CMS.LIFECYCLE_PHASES alter column UUID not null; +alter table CCM_CMS.LIFECYCLE_PHASES + add constraint UK_bkk376s9kchydlkuq052shnh5 unique (uuid); +