Merge commit '1132d0efc9f0f022fa41c019c563339e1abffc13' into dmp-refactoring

This commit is contained in:
CITE\amentis 2024-10-02 16:43:16 +03:00
commit 967a733e7f
180 changed files with 3473 additions and 712 deletions

View File

@ -52,17 +52,17 @@
<dependency>
<groupId>gr.cite</groupId>
<artifactId>oidc-authz</artifactId>
<version>2.1.0</version>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.opencdmp</groupId>
<artifactId>repositorydepositbase</artifactId>
<version>2.0.16</version>
<version>2.0.17</version>
</dependency>
<dependency>
<groupId>org.opencdmp</groupId>
<artifactId>common-models</artifactId>
<version>0.0.19</version>
<version>0.0.20</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
@ -72,7 +72,7 @@
<dependency>
<groupId>org.opencdmp</groupId>
<artifactId>file-transformer-base</artifactId>
<version>0.0.24</version>
<version>0.0.25</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>

View File

@ -50,6 +50,7 @@ public class AuditableAction {
public static final EventId Plan_GetPublicXml = new EventId(5017, "Plan_GetPublicXml");
public static final EventId Plan_ExportPublic = new EventId(5018, "Plan_ExportPublic");
public static final EventId Plan_PublicClone = new EventId(5019, "Plan_PublicClone");
public static final EventId Plan_SetStatus = new EventId(5020, "Plan_SetStatus");
public static final EventId Description_Query = new EventId(6000, "Description_Query");

View File

@ -0,0 +1,30 @@
package org.opencdmp.commons.enums;
import com.fasterxml.jackson.annotation.JsonValue;
import org.opencdmp.data.converters.enums.DatabaseEnum;
import java.util.Map;
public enum DescriptionStatusAvailableActionType implements DatabaseEnum<Short> {
Export((short) 0);
private final Short value;
DescriptionStatusAvailableActionType(Short value) {
this.value = value;
}
@Override
@JsonValue
public Short getValue() {
return this.value;
}
private static final Map<Short, DescriptionStatusAvailableActionType> map = EnumUtils.getEnumValueMap(DescriptionStatusAvailableActionType.class);
public static DescriptionStatusAvailableActionType of(Short i) {
return map.get(i);
}
}

View File

@ -0,0 +1,31 @@
package org.opencdmp.commons.enums;
import com.fasterxml.jackson.annotation.JsonValue;
import org.opencdmp.data.converters.enums.DatabaseEnum;
import java.util.Map;
public enum PlanStatusAvailableActionType implements DatabaseEnum<Short> {
Deposit((short) 0),
Export((short) 1);
private final Short value;
PlanStatusAvailableActionType(Short value) {
this.value = value;
}
@Override
@JsonValue
public Short getValue() {
return this.value;
}
private static final Map<Short, PlanStatusAvailableActionType> map = EnumUtils.getEnumValueMap(PlanStatusAvailableActionType.class);
public static PlanStatusAvailableActionType of(Short i) {
return map.get(i);
}
}

View File

@ -11,11 +11,13 @@ public class NotificationProperties {
private UUID planInvitationExistingUserType;
private UUID planModifiedType;
private UUID planFinalisedType;
private UUID planStatusChangedType;
private UUID planAnnotationCreatedType;
private UUID planAnnotationStatusChangedType;
private UUID descriptionCreatedType;
private UUID descriptionModifiedType;
private UUID descriptionFinalisedType;
private UUID descriptionStatusChangedType;
private UUID descriptionAnnotationCreatedType;
private UUID descriptionAnnotationStatusChangedType;
private UUID mergeAccountConfirmationType;
@ -61,6 +63,14 @@ public class NotificationProperties {
this.planFinalisedType = planFinalisedType;
}
public UUID getPlanStatusChangedType() {
return planStatusChangedType;
}
public void setPlanStatusChangedType(UUID planStatusChangedType) {
this.planStatusChangedType = planStatusChangedType;
}
public UUID getPlanAnnotationCreatedType() {
return planAnnotationCreatedType;
}
@ -101,6 +111,14 @@ public class NotificationProperties {
this.descriptionFinalisedType = descriptionFinalisedType;
}
public UUID getDescriptionStatusChangedType() {
return descriptionStatusChangedType;
}
public void setDescriptionStatusChangedType(UUID descriptionStatusChangedType) {
this.descriptionStatusChangedType = descriptionStatusChangedType;
}
public UUID getMergeAccountConfirmationType() {
return this.mergeAccountConfirmationType;
}

View File

@ -10,14 +10,14 @@ public class RecentActivityItemEntity {
private UUID id;
private Instant updatedAt;
private String label;
private Short statusValue;
private UUID statusId;
public RecentActivityItemEntity(RecentActivityItemType type, UUID id, Instant updatedAt, String label, Short statusValue) {
public RecentActivityItemEntity(RecentActivityItemType type, UUID id, Instant updatedAt, String label, UUID statusId) {
this.type = type;
this.id = id;
this.updatedAt = updatedAt;
this.label = label;
this.statusValue = statusValue;
this.statusId = statusId;
}
public RecentActivityItemType getType() {
@ -52,11 +52,11 @@ public class RecentActivityItemEntity {
this.label = label;
}
public Short getStatusValue() {
return statusValue;
public UUID getStatusId() {
return statusId;
}
public void setStatusValue(Short statusValue) {
this.statusValue = statusValue;
public void setStatusId(UUID statusId) {
this.statusId = statusId;
}
}

View File

@ -22,6 +22,9 @@ public class DescriptionImportExport {
@XmlElement(name = "label")
private String label;
@XmlElement(name = "status")
private DescriptionStatusImportExport status;
@XmlElement(name = "finalizedAt")
@XmlJavaTypeAdapter(InstantXmlAdapter.class)
private Instant finalizedAt;
@ -67,6 +70,14 @@ public class DescriptionImportExport {
this.label = label;
}
public DescriptionStatusImportExport getStatus() {
return status;
}
public void setStatus(DescriptionStatusImportExport status) {
this.status = status;
}
public Instant getFinalizedAt() {
return this.finalizedAt;
}

View File

@ -0,0 +1,26 @@
package org.opencdmp.commons.types.description.importexport;
import java.util.UUID;
public class DescriptionStatusImportExport {
private UUID id;
private String name;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -1,9 +1,9 @@
package org.opencdmp.commons.types.descriptionstatus;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.*;
import org.opencdmp.commons.enums.DescriptionStatusAvailableActionType;
import java.util.List;
@XmlRootElement(name = "definition")
@XmlAccessorType(XmlAccessType.FIELD)
@ -12,7 +12,19 @@ public class DescriptionStatusDefinitionEntity {
@XmlElement(name = "authorization")
private DescriptionStatusDefinitionAuthorizationEntity authorization;
@XmlElementWrapper(name = "availableActions")
@XmlElement(name = "action")
private List<DescriptionStatusAvailableActionType> availableActions;
public DescriptionStatusDefinitionAuthorizationEntity getAuthorization() { return this.authorization; }
public void setAuthorization(DescriptionStatusDefinitionAuthorizationEntity authorization) { this.authorization = authorization; }
public List<DescriptionStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<DescriptionStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
}

View File

@ -30,6 +30,9 @@ public class PlanImportExport {
@XmlElement(name = "access")
private PlanAccessType access;
@XmlElement(name = "status")
private PlanStatusImportExport status;
@XmlElement(name = "version")
private Short version;
@ -109,6 +112,14 @@ public class PlanImportExport {
this.access = access;
}
public PlanStatusImportExport getStatus() {
return status;
}
public void setStatus(PlanStatusImportExport status) {
this.status = status;
}
public List<PlanContactImportExport> getContacts() {
return this.contacts;
}

View File

@ -0,0 +1,26 @@
package org.opencdmp.commons.types.plan.importexport;
import java.util.UUID;
public class PlanStatusImportExport {
private UUID id;
private String name;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -1,6 +1,9 @@
package org.opencdmp.commons.types.planstatus;
import jakarta.xml.bind.annotation.*;
import org.opencdmp.commons.enums.PlanStatusAvailableActionType;
import java.util.List;
@XmlRootElement(name = "definition")
@XmlAccessorType(XmlAccessType.FIELD)
@ -9,9 +12,21 @@ public class PlanStatusDefinitionEntity {
@XmlElement(name = "authorization")
private PlanStatusDefinitionAuthorizationEntity authorization;
@XmlElementWrapper(name = "availableActions")
@XmlElement(name = "action")
private List<PlanStatusAvailableActionType> availableActions;
public PlanStatusDefinitionAuthorizationEntity getAuthorization() {
return this.authorization;
}
public void setAuthorization(PlanStatusDefinitionAuthorizationEntity authorization) { this.authorization = authorization; }
public List<PlanStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<PlanStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
}

View File

@ -39,6 +39,10 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
private DescriptionStatus status;
public static final String _status = "status";
@Column(name = "status_id", nullable = true)
private UUID statusId;
public static final String _statusId = "statusId";
@Column(name = "description")
private String description;
@ -187,5 +191,13 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
public void setDescriptionTemplateId(UUID descriptionTemplateId) {
this.descriptionTemplateId = descriptionTemplateId;
}
public UUID getStatusId() {
return statusId;
}
public void setStatusId(UUID statusId) {
this.statusId = statusId;
}
}

View File

@ -29,6 +29,11 @@ public class DescriptionStatusEntity extends TenantScopedBaseEntity {
private String description;
public static final String _description = "description";
@Column(name = "action", length = DescriptionStatusEntity._nameLength, nullable = true)
private String action;
public static final String _action = "action";
public static final int _actionLength = 250;
@Column(name = "created_at", nullable = false)
private Instant createdAt;
public static final String _createdAt = "createdAt";
@ -74,6 +79,14 @@ public class DescriptionStatusEntity extends TenantScopedBaseEntity {
this.createdAt = createdAt;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public Instant getUpdatedAt() {
return this.updatedAt;
}

View File

@ -47,6 +47,10 @@ public class PlanEntity extends TenantScopedBaseEntity {
public static final String _status = "status";
@Column(name = "status_id", nullable = true)
private UUID statusId;
public static final String _statusId = "statusId";
@Column(name = "properties", nullable = true)
private String properties;
@ -141,6 +145,14 @@ public class PlanEntity extends TenantScopedBaseEntity {
this.status = status;
}
public UUID getStatusId() {
return statusId;
}
public void setStatusId(UUID statusId) {
this.statusId = statusId;
}
public String getProperties() {
return this.properties;
}

View File

@ -29,6 +29,11 @@ public class PlanStatusEntity extends TenantScopedBaseEntity {
private String description;
public static final String _description = "description";
@Column(name = "action", length = PlanStatusEntity._actionLength, nullable = true)
private String action;
public static final String _action = "action";
public static final int _actionLength = 250;
@Column(name = "created_at", nullable = false)
private Instant createdAt;
public static final String _createdAt = "createdAt";
@ -67,6 +72,14 @@ public class PlanStatusEntity extends TenantScopedBaseEntity {
public String getDescription() { return this.description; }
public void setDescription(String description) { this.description = description;}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public Instant getCreatedAt() {
return this.createdAt;
}

View File

@ -33,9 +33,9 @@ public class DescriptionElasticEntity {
private String description;
public final static String _description = "description";
@Field(value = DescriptionElasticEntity._status, type = FieldType.Short)
private DescriptionStatus status;
public final static String _status = "status";
@Field(value = DescriptionElasticEntity._statusId, type = FieldType.Keyword)
private UUID statusId;
public final static String _statusId = "statusId";
@Field(value = DescriptionElasticEntity._finalizedAt, type = FieldType.Date)
private Date finalizedAt;
@ -97,12 +97,12 @@ public class DescriptionElasticEntity {
this.description = description;
}
public DescriptionStatus getStatus() {
return this.status;
public UUID getStatusId() {
return statusId;
}
public void setStatus(DescriptionStatus status) {
this.status = status;
public void setStatusId(UUID statusId) {
this.statusId = statusId;
}
public Date getFinalizedAt() {

View File

@ -35,9 +35,9 @@ public class PlanElasticEntity {
private Short version;
public final static String _version = "version";
@Field(value = PlanElasticEntity._status, type = FieldType.Short)
private PlanStatus status;
public final static String _status = "status";
@Field(value = PlanElasticEntity._statusId, type = FieldType.Keyword)
private UUID statusId;
public final static String _statusId = "statusId";
@Field(value = PlanElasticEntity._accessType, type = FieldType.Short)
private PlanAccessType accessType;
@ -130,12 +130,12 @@ public class PlanElasticEntity {
this.version = version;
}
public PlanStatus getStatus() {
return this.status;
public UUID getStatusId() {
return statusId;
}
public void setStatus(PlanStatus status) {
this.status = status;
public void setStatusId(UUID statusId) {
this.statusId = statusId;
}
public PlanAccessType getAccessType() {

View File

@ -35,9 +35,9 @@ public class NestedPlanElasticEntity {
private PlanVersionStatus versionStatus;
public final static String _versionStatus = "versionStatus";
@Field(value = NestedPlanElasticEntity._status, type = FieldType.Short)
private PlanStatus status;
public final static String _status = "status";
@Field(value = NestedPlanElasticEntity._statusId, type = FieldType.Keyword)
private UUID statusId;
public final static String _statusId = "statusId";
@Field(value = NestedPlanElasticEntity._accessType, type = FieldType.Short)
private PlanAccessType accessType;
@ -103,12 +103,12 @@ public class NestedPlanElasticEntity {
this.version = version;
}
public PlanStatus getStatus() {
return status;
public UUID getStatusId() {
return statusId;
}
public void setStatus(PlanStatus status) {
this.status = status;
public void setStatusId(UUID statusId) {
this.statusId = statusId;
}
public PlanAccessType getAccessType() {

View File

@ -63,7 +63,7 @@ public class DescriptionElasticBuilder extends BaseElasticBuilder<DescriptionEla
m.setId(d.getId());
m.setLabel(d.getLabel());
m.setDescription(d.getDescription());
m.setStatus(d.getStatus());
m.setStatusId(d.getStatusId());
m.setCreatedAt(Date.from(d.getCreatedAt()));
m.setUpdatedAt(Date.from(d.getUpdatedAt()));
if (d.getFinalizedAt() != null) {

View File

@ -55,7 +55,7 @@ public class PlanElasticBuilder extends BaseElasticBuilder<PlanElasticEntity, Pl
m.setDescription(d.getDescription());
m.setVersion(d.getVersion());
m.setVersionStatus(d.getVersionStatus());
m.setStatus(d.getStatus());
m.setStatusId(d.getStatusId());
m.setAccessType(d.getAccessType());
m.setLanguage(d.getLanguage());
m.setBlueprintId(d.getBlueprintId());

View File

@ -60,7 +60,7 @@ public class NestedPlanElasticBuilder extends BaseElasticBuilder<NestedPlanElast
m.setLabel(d.getLabel());
m.setDescription(d.getDescription());
m.setVersion(d.getVersion());
m.setStatus(d.getStatus());
m.setStatusId(d.getStatusId());
m.setAccessType(d.getAccessType());
m.setLanguage(d.getLanguage());
m.setBlueprintId(d.getBlueprintId());

View File

@ -50,7 +50,7 @@ public class DescriptionElasticQuery extends ElasticQuery<DescriptionElasticEnti
private Instant finalizedBefore;
private Collection<UUID> excludedIds;
private Collection<UUID> tenantIds;
private Collection<DescriptionStatus> statuses;
private Collection<UUID> statusIds;
private NestedDescriptionTemplateElasticQuery descriptionTemplateSubQuery;
private NestedReferenceElasticQuery referenceSubQuery;
private NestedTagElasticQuery tagSubQuery;
@ -133,18 +133,18 @@ public class DescriptionElasticQuery extends ElasticQuery<DescriptionElasticEnti
return this;
}
public DescriptionElasticQuery statuses(DescriptionStatus value) {
this.statuses = List.of(value);
public DescriptionElasticQuery statusIds(UUID value) {
this.statusIds = List.of(value);
return this;
}
public DescriptionElasticQuery statuses(DescriptionStatus... value) {
this.statuses = Arrays.asList(value);
public DescriptionElasticQuery statusIds(UUID... value) {
this.statusIds = Arrays.asList(value);
return this;
}
public DescriptionElasticQuery statuses(Collection<DescriptionStatus> values) {
this.statuses = values;
public DescriptionElasticQuery statusIds(Collection<UUID> values) {
this.statusIds = values;
return this;
}
@ -189,7 +189,7 @@ public class DescriptionElasticQuery extends ElasticQuery<DescriptionElasticEnti
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) ||
this.isEmpty(this.excludedIds) ||
this.isEmpty(this.statuses);
this.isEmpty(this.statusIds);
}
@Override
@ -230,7 +230,7 @@ public class DescriptionElasticQuery extends ElasticQuery<DescriptionElasticEnti
List<Query> predicates = new ArrayList<>();
if (usePublic ) {
predicates.add(this.and(
this.equals(new ElasticField(DescriptionElasticEntity._plan + "." + PlanElasticEntity._status, this.entityClass()).disableInfer(true), PlanStatus.Finalized.getValue()),
this.equals(new ElasticField(DescriptionElasticEntity._plan + "." + PlanElasticEntity._statusId, this.entityClass()).disableInfer(true), PlanStatus.Finalized.getValue()),
this.equals(new ElasticField(DescriptionElasticEntity._plan + "." + PlanElasticEntity._accessType, this.entityClass()).disableInfer(true), PlanAccessType.Public.getValue())
));
}
@ -284,8 +284,8 @@ public class DescriptionElasticQuery extends ElasticQuery<DescriptionElasticEnti
if (this.tenantIds != null) {
predicates.add(this.containsUUID(this.elasticFieldOf(DescriptionElasticEntity._tenantId), this.tenantIds)._toQuery());
}
if (this.statuses != null) {
predicates.add(this.contains(this.elasticFieldOf(DescriptionElasticEntity._status), this.statuses.stream().map(DescriptionStatus::getValue).toList().toArray(new Short[this.statuses.size()]))._toQuery());
if (this.statusIds != null) {
predicates.add(this.containsUUID(this.elasticFieldOf(DescriptionElasticEntity._statusId), this.statusIds)._toQuery());
}
if (this.finalizedAfter != null) {
predicates.add(this.dateGreaterThanQuery(this.elasticFieldOf(DescriptionElasticEntity._finalizedAt), this.finalizedAfter)._toQuery());
@ -324,7 +324,7 @@ public class DescriptionElasticQuery extends ElasticQuery<DescriptionElasticEnti
if (columns.contains(DescriptionElasticEntity._id)) mocDoc.setId(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._id), UUID.class));
if (columns.contains(DescriptionElasticEntity._label)) mocDoc.setLabel(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._label), String.class));
if (columns.contains(DescriptionElasticEntity._description)) mocDoc.setDescription(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._description), String.class));
if (columns.contains(DescriptionElasticEntity._status)) mocDoc.setStatus(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._status), DescriptionStatus.class));
if (columns.contains(DescriptionElasticEntity._statusId)) mocDoc.setStatusId(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._statusId), UUID.class));
if (columns.contains(DescriptionElasticEntity._finalizedAt)) mocDoc.setFinalizedAt(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._finalizedAt), Date.class));
if (columns.contains(DescriptionElasticEntity._createdAt)) mocDoc.setCreatedAt(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._createdAt), Date.class));
if (columns.contains(DescriptionElasticEntity._updatedAt)) mocDoc.setUpdatedAt(FieldBasedMapper.shallowSafeConversion(rawData.get(DescriptionElasticEntity._updatedAt), Date.class));
@ -340,7 +340,7 @@ public class DescriptionElasticQuery extends ElasticQuery<DescriptionElasticEnti
if (item.match(DescriptionElasticEntity._id)) return this.elasticFieldOf(DescriptionElasticEntity._id);
else if (item.match(DescriptionElasticEntity._label)) return item instanceof OrderingFieldResolver ? this.elasticFieldOf(DescriptionElasticEntity._label).subfield(ElasticConstants.SubFields.keyword) : this.elasticFieldOf(DescriptionElasticEntity._label);
else if (item.match(DescriptionElasticEntity._description)) return this.elasticFieldOf(DescriptionElasticEntity._description);
else if (item.match(DescriptionElasticEntity._status)) return this.elasticFieldOf(DescriptionElasticEntity._status);
else if (item.match(DescriptionElasticEntity._statusId)) return this.elasticFieldOf(DescriptionElasticEntity._statusId);
else if (item.match(DescriptionElasticEntity._finalizedAt)) return this.elasticFieldOf(DescriptionElasticEntity._finalizedAt);
else if (item.match(DescriptionElasticEntity._createdAt)) return this.elasticFieldOf(DescriptionElasticEntity._createdAt);
else if (item.match(DescriptionElasticEntity._updatedAt)) return this.elasticFieldOf(DescriptionElasticEntity._updatedAt);

View File

@ -30,7 +30,7 @@ public class InnerObjectPlanElasticQuery extends ElasticInnerObjectQuery<InnerOb
private String like;
private Collection<UUID> ids;
private Collection<UUID> excludedIds;
private Collection<PlanStatus> statuses;
private Collection<UUID> statusIds;
private Collection<PlanVersionStatus> versionStatuses;
private Collection<PlanAccessType> accessTypes;
private Collection<Integer> versions;
@ -108,18 +108,18 @@ public class InnerObjectPlanElasticQuery extends ElasticInnerObjectQuery<InnerOb
return this;
}
public InnerObjectPlanElasticQuery statuses(PlanStatus value) {
this.statuses = List.of(value);
public InnerObjectPlanElasticQuery statusIds(UUID value) {
this.statusIds = List.of(value);
return this;
}
public InnerObjectPlanElasticQuery statuses(PlanStatus... value) {
this.statuses = Arrays.asList(value);
public InnerObjectPlanElasticQuery statusIds(UUID... value) {
this.statusIds = Arrays.asList(value);
return this;
}
public InnerObjectPlanElasticQuery statuses(Collection<PlanStatus> values) {
this.statuses = values;
public InnerObjectPlanElasticQuery statusIds(Collection<UUID> values) {
this.statusIds = values;
return this;
}
@ -203,8 +203,8 @@ public class InnerObjectPlanElasticQuery extends ElasticInnerObjectQuery<InnerOb
if (this.excludedIds != null) {
predicates.add(this.not(this.containsUUID(this.elasticFieldOf(NestedPlanElasticEntity._id).disableInfer(true), this.excludedIds)._toQuery())._toQuery());
}
if (this.statuses != null) {
predicates.add(this.contains(this.elasticFieldOf(NestedPlanElasticEntity._status).disableInfer(true), this.statuses.stream().map(x-> x.getValue()).collect(Collectors.toList()).toArray(new Short[this.statuses.size()]))._toQuery());
if (this.statusIds != null) {
predicates.add(this.containsUUID(this.elasticFieldOf(NestedPlanElasticEntity._id).disableInfer(true), this.statusIds)._toQuery());
}
if (this.versionStatuses != null) {
predicates.add(this.contains(this.elasticFieldOf(NestedPlanElasticEntity._versionStatus).disableInfer(true), this.versionStatuses.stream().map(x-> x.getValue()).collect(Collectors.toList()).toArray(new Short[this.versionStatuses.size()]))._toQuery());
@ -229,7 +229,7 @@ public class InnerObjectPlanElasticQuery extends ElasticInnerObjectQuery<InnerOb
if (columns.contains(NestedPlanElasticEntity._id)) mocDoc.setId(FieldBasedMapper.shallowSafeConversion(rawData.get(NestedPlanElasticEntity._id), UUID.class));
if (columns.contains(NestedPlanElasticEntity._label)) mocDoc.setLabel(FieldBasedMapper.shallowSafeConversion(rawData.get(NestedPlanElasticEntity._label), String.class));
if (columns.contains(NestedPlanElasticEntity._description)) mocDoc.setDescription(FieldBasedMapper.shallowSafeConversion(rawData.get(NestedPlanElasticEntity._description), String.class));
if (columns.contains(NestedPlanElasticEntity._status)) mocDoc.setStatus(FieldBasedMapper.shallowSafeConversion(rawData.get(NestedPlanElasticEntity._status), PlanStatus.class));
if (columns.contains(NestedPlanElasticEntity._statusId)) mocDoc.setStatusId(FieldBasedMapper.shallowSafeConversion(rawData.get(NestedPlanElasticEntity._statusId), UUID.class));
if (columns.contains(NestedPlanElasticEntity._versionStatus)) mocDoc.setVersionStatus(FieldBasedMapper.shallowSafeConversion(rawData.get(NestedPlanElasticEntity._versionStatus), PlanVersionStatus.class));
if (columns.contains(NestedPlanElasticEntity._version)) mocDoc.setVersion(FieldBasedMapper.shallowSafeConversion(rawData.get(NestedPlanElasticEntity._version), Short.class));
if (columns.contains(NestedPlanElasticEntity._groupId)) mocDoc.setGroupId(FieldBasedMapper.shallowSafeConversion(rawData.get(NestedPlanElasticEntity._groupId), UUID.class));
@ -245,7 +245,7 @@ public class InnerObjectPlanElasticQuery extends ElasticInnerObjectQuery<InnerOb
if (item.match(NestedPlanElasticEntity._id)) return this.elasticFieldOf(NestedPlanElasticEntity._id);
else if (item.match(NestedPlanElasticEntity._label)) return this.elasticFieldOf(NestedPlanElasticEntity._label);
else if (item.match(NestedPlanElasticEntity._description)) return this.elasticFieldOf(NestedPlanElasticEntity._description);
else if (item.match(NestedPlanElasticEntity._status)) return this.elasticFieldOf(NestedPlanElasticEntity._status);
else if (item.match(NestedPlanElasticEntity._statusId)) return this.elasticFieldOf(NestedPlanElasticEntity._statusId);
else if (item.match(NestedPlanElasticEntity._versionStatus)) return this.elasticFieldOf(NestedPlanElasticEntity._versionStatus);
else if (item.match(NestedPlanElasticEntity._version)) return this.elasticFieldOf(NestedPlanElasticEntity._version);
else if (item.match(NestedPlanElasticEntity._groupId)) return this.elasticFieldOf(NestedPlanElasticEntity._groupId);

View File

@ -42,7 +42,7 @@ public class PlanElasticQuery extends ElasticQuery<PlanElasticEntity, UUID> {
private String like;
private Collection<UUID> ids;
private Collection<UUID> excludedIds;
private Collection<PlanStatus> statuses;
private Collection<UUID> statusIds;
private Collection<PlanVersionStatus> versionStatuses;
private Collection<PlanAccessType> accessTypes;
private Collection<Integer> versions;
@ -140,18 +140,18 @@ public class PlanElasticQuery extends ElasticQuery<PlanElasticEntity, UUID> {
return this;
}
public PlanElasticQuery statuses(PlanStatus value) {
this.statuses = List.of(value);
public PlanElasticQuery statuses(UUID value) {
this.statusIds = List.of(value);
return this;
}
public PlanElasticQuery statuses(PlanStatus... value) {
this.statuses = Arrays.asList(value);
public PlanElasticQuery statuses(UUID... value) {
this.statusIds = Arrays.asList(value);
return this;
}
public PlanElasticQuery statuses(Collection<PlanStatus> values) {
this.statuses = values;
public PlanElasticQuery statuses(Collection<UUID> values) {
this.statusIds = values;
return this;
}
@ -224,7 +224,7 @@ public class PlanElasticQuery extends ElasticQuery<PlanElasticEntity, UUID> {
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.versionStatuses) || this.isEmpty(this.excludedIds) || this.isEmpty(this.accessTypes)|| this.isEmpty(this.statuses);
return this.isEmpty(this.ids) || this.isEmpty(this.versionStatuses) || this.isEmpty(this.excludedIds) || this.isEmpty(this.accessTypes)|| this.isEmpty(this.statusIds);
}
@Override
@ -265,7 +265,7 @@ public class PlanElasticQuery extends ElasticQuery<PlanElasticEntity, UUID> {
List<Query> predicates = new ArrayList<>();
if (usePublic) {
predicates.add(this.and(
this.equals(this.elasticFieldOf(PlanElasticEntity._status), PlanStatus.Finalized.getValue()),
this.equals(this.elasticFieldOf(PlanElasticEntity._statusId), PlanStatus.Finalized.getValue()),
this.equals(this.elasticFieldOf(PlanElasticEntity._accessType), PlanAccessType.Public.getValue())
));
}
@ -328,8 +328,8 @@ public class PlanElasticQuery extends ElasticQuery<PlanElasticEntity, UUID> {
if (this.excludedIds != null) {
predicates.add(this.not(this.containsUUID(this.elasticFieldOf(PlanElasticEntity._id), this.excludedIds)._toQuery())._toQuery());
}
if (this.statuses != null) {
predicates.add(this.contains(this.elasticFieldOf(PlanElasticEntity._status), this.statuses.stream().map(PlanStatus::getValue).toList().toArray(new Short[this.statuses.size()]))._toQuery());
if (this.statusIds != null) {
predicates.add(this.containsUUID(this.elasticFieldOf(PlanElasticEntity._statusId), this.statusIds)._toQuery());
}
if (this.versionStatuses != null) {
predicates.add(this.contains(this.elasticFieldOf(PlanElasticEntity._versionStatus), this.versionStatuses.stream().map(PlanVersionStatus::getValue).toList().toArray(new Short[this.versionStatuses.size()]))._toQuery());
@ -363,7 +363,7 @@ public class PlanElasticQuery extends ElasticQuery<PlanElasticEntity, UUID> {
if (columns.contains(PlanElasticEntity._id)) mocDoc.setId(FieldBasedMapper.shallowSafeConversion(rawData.get(PlanElasticEntity._id), UUID.class));
if (columns.contains(PlanElasticEntity._label)) mocDoc.setLabel(FieldBasedMapper.shallowSafeConversion(rawData.get(PlanElasticEntity._label), String.class));
if (columns.contains(PlanElasticEntity._description)) mocDoc.setDescription(FieldBasedMapper.shallowSafeConversion(rawData.get(PlanElasticEntity._description), String.class));
if (columns.contains(PlanElasticEntity._status)) mocDoc.setStatus(FieldBasedMapper.shallowSafeConversion(rawData.get(PlanElasticEntity._status), PlanStatus.class));
if (columns.contains(PlanElasticEntity._statusId)) mocDoc.setStatusId(FieldBasedMapper.shallowSafeConversion(rawData.get(PlanElasticEntity._statusId), UUID.class));
if (columns.contains(PlanElasticEntity._versionStatus)) mocDoc.setVersionStatus(FieldBasedMapper.shallowSafeConversion(rawData.get(PlanElasticEntity._versionStatus), PlanVersionStatus.class));
if (columns.contains(PlanElasticEntity._version)) mocDoc.setVersion(FieldBasedMapper.shallowSafeConversion(rawData.get(PlanElasticEntity._version), Short.class));
if (columns.contains(PlanElasticEntity._groupId)) mocDoc.setGroupId(FieldBasedMapper.shallowSafeConversion(rawData.get(PlanElasticEntity._groupId), UUID.class));
@ -383,7 +383,7 @@ public class PlanElasticQuery extends ElasticQuery<PlanElasticEntity, UUID> {
if (item.match(PlanElasticEntity._id)) return this.elasticFieldOf(PlanElasticEntity._id);
else if (item.match(PlanElasticEntity._label)) return item instanceof OrderingFieldResolver ? this.elasticFieldOf(PlanElasticEntity._label).subfield(ElasticConstants.SubFields.keyword) : this.elasticFieldOf(PlanElasticEntity._label);
else if (item.match(PlanElasticEntity._description)) return this.elasticFieldOf(PlanElasticEntity._description);
else if (item.match(PlanElasticEntity._status)) return this.elasticFieldOf(PlanElasticEntity._status);
else if (item.match(PlanElasticEntity._statusId)) return this.elasticFieldOf(PlanElasticEntity._statusId);
else if (item.match(PlanElasticEntity._version)) return this.elasticFieldOf(PlanElasticEntity._version);
else if (item.match(PlanElasticEntity._versionStatus)) return this.elasticFieldOf(PlanElasticEntity._versionStatus);
else if (item.match(PlanElasticEntity._groupId)) return this.elasticFieldOf(PlanElasticEntity._groupId);

View File

@ -0,0 +1,35 @@
package org.opencdmp.event;
import java.util.UUID;
public class DescriptionStatusTouchedEvent {
public DescriptionStatusTouchedEvent() {
}
public DescriptionStatusTouchedEvent(UUID id, String tenantCode) {
this.id = id;
this.tenantCode = tenantCode;
}
private UUID id;
private String tenantCode;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getTenantCode() {
return tenantCode;
}
public void setTenantCode(String tenantCode) {
this.tenantCode = tenantCode;
}
}

View File

@ -53,6 +53,14 @@ public class EventBroker {
this.applicationEventPublisher.publishEvent(event);
}
public void emit(PlanStatusTouchedEvent event) {
this.applicationEventPublisher.publishEvent(event);
}
public void emit(DescriptionStatusTouchedEvent event) {
this.applicationEventPublisher.publishEvent(event);
}
public void emit(TagTouchedEvent event) {
this.applicationEventPublisher.publishEvent(event);
}

View File

@ -0,0 +1,34 @@
package org.opencdmp.event;
import java.util.UUID;
public class PlanStatusTouchedEvent {
public PlanStatusTouchedEvent() {
}
public PlanStatusTouchedEvent(UUID id, String tenantCode) {
this.id = id;
this.tenantCode = tenantCode;
}
private UUID id;
private String tenantCode;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getTenantCode() {
return tenantCode;
}
public void setTenantCode(String tenantCode) {
this.tenantCode = tenantCode;
}
}

View File

@ -22,3 +22,4 @@ public class PlanTouchedEvent {
}
}

View File

@ -1,6 +1,5 @@
package org.opencdmp.model;
import org.opencdmp.commons.enums.DescriptionStatus;
import java.time.Instant;
import java.util.UUID;
@ -15,7 +14,7 @@ public class PublicDescription {
public static final String _label = "label";
private DescriptionStatus status;
private PublicDescriptionStatus status;
public static final String _status = "status";
@ -65,11 +64,11 @@ public class PublicDescription {
}
public DescriptionStatus getStatus() {
public PublicDescriptionStatus getStatus() {
return status;
}
public void setStatus(DescriptionStatus status) {
public void setStatus(PublicDescriptionStatus status) {
this.status = status;
}

View File

@ -0,0 +1,36 @@
package org.opencdmp.model;
import java.util.UUID;
public class PublicDescriptionStatus {
public final static String _id = "id";
private UUID id;
public final static String _name = "name";
private String name;
public final static String _internalStatus = "internalStatus";
private org.opencdmp.commons.enums.DescriptionStatus internalStatus;
public final static String _definition = "definition";
private PublicDescriptionStatusDefinition definition;
public UUID getId() { return this.id; }
public void setId(UUID id) { this.id = id; }
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public org.opencdmp.commons.enums.DescriptionStatus getInternalStatus() { return this.internalStatus; }
public void setInternalStatus(org.opencdmp.commons.enums.DescriptionStatus internalStatus) { this.internalStatus = internalStatus; }
public PublicDescriptionStatusDefinition getDefinition() {
return definition;
}
public void setDefinition(PublicDescriptionStatusDefinition definition) {
this.definition = definition;
}
}

View File

@ -0,0 +1,20 @@
package org.opencdmp.model;
import org.opencdmp.commons.enums.DescriptionStatusAvailableActionType;
import java.util.List;
public class PublicDescriptionStatusDefinition {
public final static String _availableActions = "availableActions";
private List<DescriptionStatusAvailableActionType> availableActions;
public List<DescriptionStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<DescriptionStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
}

View File

@ -1,7 +1,6 @@
package org.opencdmp.model;
import org.opencdmp.commons.enums.PlanAccessType;
import org.opencdmp.commons.enums.PlanStatus;
import java.time.Instant;
import java.util.List;
@ -36,7 +35,7 @@ public class PublicPlan {
public static final String _publishedAt = "publishedAt";
private PlanStatus status;
private PublicPlanStatus status;
public static final String _status = "status";
private UUID groupId;
@ -118,11 +117,11 @@ public class PublicPlan {
this.publishedAt = publishedAt;
}
public PlanStatus getStatus() {
public PublicPlanStatus getStatus() {
return status;
}
public void setStatus(PlanStatus status) {
public void setStatus(PublicPlanStatus status) {
this.status = status;
}

View File

@ -0,0 +1,43 @@
package org.opencdmp.model;
import org.opencdmp.commons.enums.PlanStatus;
import java.util.UUID;
public class PublicPlanStatus {
public final static String _id = "id";
private UUID id;
public final static String _name = "name";
private String name;
public final static String _internalStatus = "internalStatus";
private PlanStatus internalStatus;
public final static String _definition = "definition";
private PublicPlanStatusDefinition definition;
public UUID getId() { return this.id; }
public void setId(UUID id) { this.id = id; }
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public PlanStatus getInternalStatus() {
return internalStatus;
}
public void setInternalStatus(PlanStatus internalStatus) {
this.internalStatus = internalStatus;
}
public PublicPlanStatusDefinition getDefinition() {
return definition;
}
public void setDefinition(PublicPlanStatusDefinition definition) {
this.definition = definition;
}
}

View File

@ -0,0 +1,21 @@
package org.opencdmp.model;
import org.opencdmp.commons.enums.PlanStatusAvailableActionType;
import java.util.List;
public class PublicPlanStatusDefinition {
public final static String _availableActions = "availableActions";
private List<PlanStatusAvailableActionType> availableActions;
public List<PlanStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<PlanStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
}

View File

@ -6,9 +6,7 @@ import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.enums.RecentActivityOrder;
import org.opencdmp.model.description.Description;
import org.opencdmp.model.plan.Plan;
import org.opencdmp.query.lookup.DescriptionLookup;
import org.opencdmp.query.lookup.PlanLookup;
import org.opencdmp.query.lookup.PlanUserLookup;
import org.opencdmp.query.lookup.*;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.Paging;
import gr.cite.tools.fieldset.BaseFieldSet;
@ -97,8 +95,12 @@ public class RecentActivityItemLookup{
DescriptionLookup lookup = new DescriptionLookup();
lookup.setIsActive(List.of(IsActive.Active));
if (this.like != null) lookup.setLike(this.like);
if (this.onlyDraft != null) lookup.setStatuses(List.of(DescriptionStatus.Draft));
else lookup.setStatuses(List.of(DescriptionStatus.Draft, DescriptionStatus.Finalized));
if (this.onlyDraft != null) {
DescriptionStatusLookup descriptionStatusLookup = new DescriptionStatusLookup();
descriptionStatusLookup.setInternalStatuses(List.of(DescriptionStatus.Draft));
descriptionStatusLookup.setIsActive(List.of(IsActive.Active));
lookup.setDescriptionStatusSubQuery(descriptionStatusLookup);
}
if (this.userIds != null) {
PlanLookup planLookup = new PlanLookup();
PlanUserLookup planUserLookup = new PlanUserLookup();
@ -131,7 +133,12 @@ public class RecentActivityItemLookup{
PlanLookup lookup = new PlanLookup();
lookup.setIsActive(List.of(IsActive.Active));
if (this.like != null) lookup.setLike(this.like);
if (this.onlyDraft != null) lookup.setStatuses(List.of(PlanStatus.Draft));
if (this.onlyDraft != null) {
PlanStatusLookup planStatusLookup = new PlanStatusLookup();
planStatusLookup.setInternalStatuses(List.of(PlanStatus.Draft));
planStatusLookup.setIsActive(List.of(IsActive.Active));
lookup.setPlanStatusSubQuery(planStatusLookup);
}
if (this.userIds != null) {
PlanUserLookup planUserLookup = new PlanUserLookup();
planUserLookup.setUserIds(this.userIds);

View File

@ -10,10 +10,8 @@ import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionEntity;
import org.opencdmp.model.PublicDescription;
import org.opencdmp.model.PublicDescriptionTemplate;
import org.opencdmp.model.PublicPlan;
import org.opencdmp.model.PublicPlanDescriptionTemplate;
import org.opencdmp.model.*;
import org.opencdmp.query.DescriptionStatusQuery;
import org.opencdmp.query.DescriptionTemplateQuery;
import org.opencdmp.query.PlanDescriptionTemplateQuery;
import org.opencdmp.query.PlanQuery;
@ -66,12 +64,15 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
FieldSet planFields = fields.extractPrefixed(this.asPrefix(PublicDescription._plan));
Map<UUID, PublicPlan> planItemsMap = this.collectPlans(planFields, data);
FieldSet descriptionStatusFields = fields.extractPrefixed(this.asPrefix(PublicDescription._status));
Map<UUID, PublicDescriptionStatus> descriptionStatusItemsMap = this.collectDescriptionStatuses(descriptionStatusFields, data);
List<PublicDescription> models = new ArrayList<>();
for (DescriptionEntity d : data) {
PublicDescription m = new PublicDescription();
if (fields.hasField(this.asIndexer(PublicDescription._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(PublicDescription._label))) m.setLabel(d.getLabel());
if (fields.hasField(this.asIndexer(PublicDescription._status))) m.setStatus(d.getStatus());
if (!descriptionStatusFields.isEmpty() && descriptionStatusItemsMap != null && descriptionStatusItemsMap.containsKey(d.getStatusId())) m.setStatus(descriptionStatusItemsMap.get(d.getStatusId()));
if (fields.hasField(this.asIndexer(PublicDescription._description))) m.setDescription(d.getDescription());
if (fields.hasField(this.asIndexer(PublicDescription._createdAt))) m.setCreatedAt(d.getCreatedAt());
if (fields.hasField(this.asIndexer(PublicDescription._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
@ -177,4 +178,34 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
return itemMap;
}
private Map<UUID, PublicDescriptionStatus> collectDescriptionStatuses(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty())
return null;
this.logger.debug("checking related - {}", PublicDescriptionStatus.class.getSimpleName());
Map<UUID, PublicDescriptionStatus> itemMap;
if (!fields.hasOtherField(this.asIndexer(PublicDescriptionStatus._id))) {
itemMap = this.asEmpty(
data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()),
x -> {
PublicDescriptionStatus item = new PublicDescriptionStatus();
item.setId(x);
return item;
},
PublicDescriptionStatus::getId);
} else {
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(PublicDescriptionStatus._id);
DescriptionStatusQuery q = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PublicDescriptionStatusBuilder.class).authorize(this.authorize).asForeignKey(q, clone, PublicDescriptionStatus::getId);
}
if (!fields.hasField(PublicDescriptionStatus._id)) {
itemMap.forEach((id, item) -> {
if (item != null)
item.setId(null);
});
}
return itemMap;
}
}

View File

@ -0,0 +1,68 @@
package org.opencdmp.model.builder;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionStatusEntity;
import org.opencdmp.model.PublicDescriptionStatus;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PublicDescriptionStatusBuilder extends BaseBuilder<PublicDescriptionStatus, DescriptionStatusEntity> {
private final XmlHandlingService xmlHandlingService;
private final BuilderFactory builderFactory;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PublicDescriptionStatusBuilder(
ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicDescriptionStatusBuilder.class)));
this.xmlHandlingService = xmlHandlingService;
this.builderFactory = builderFactory;
}
public PublicDescriptionStatusBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
public List<PublicDescriptionStatus> build(FieldSet fields, List<DescriptionStatusEntity> data) throws MyApplicationException {
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
this.logger.trace(new DataLogEntry("requested fields", fields));
if (fields == null || data == null || fields.isEmpty())
return new ArrayList<>();
List<PublicDescriptionStatus> models = new ArrayList<>();
FieldSet definitionFields = fields.extractPrefixed(this.asPrefix(PublicDescriptionStatus._definition));
for (DescriptionStatusEntity d : data) {
PublicDescriptionStatus m = new PublicDescriptionStatus();
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._name))) m.setName(d.getName());
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._internalStatus))) m.setInternalStatus(d.getInternalStatus());
if (!definitionFields.isEmpty() && d.getDefinition() != null) {
DescriptionStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(DescriptionStatusDefinitionEntity.class, d.getDefinition());
m.setDefinition(this.builderFactory.builder(PublicDescriptionStatusDefinitionBuilder.class).authorize(this.authorize).build(definitionFields, definition));
}
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
}

View File

@ -0,0 +1,51 @@
package org.opencdmp.model.builder;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.model.PublicDescriptionStatusDefinition;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PublicDescriptionStatusDefinitionBuilder extends BaseBuilder<PublicDescriptionStatusDefinition, DescriptionStatusDefinitionEntity> {
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PublicDescriptionStatusDefinitionBuilder(
ConventionService conventionService) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicDescriptionStatusDefinitionBuilder.class)));
}
public PublicDescriptionStatusDefinitionBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
public List<PublicDescriptionStatusDefinition> build(FieldSet fields, List<DescriptionStatusDefinitionEntity> data) throws MyApplicationException {
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
this.logger.trace(new DataLogEntry("requested fields", fields));
if (fields == null || data == null || fields.isEmpty())
return new ArrayList<>();
List<PublicDescriptionStatusDefinition> models = new ArrayList<>();
for (DescriptionStatusDefinitionEntity d : data) {
PublicDescriptionStatusDefinition m = new PublicDescriptionStatusDefinition();
if (fields.hasField(this.asIndexer(PublicDescriptionStatusDefinition._availableActions))) m.setAvailableActions(d.getAvailableActions());
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
}

View File

@ -71,6 +71,9 @@ public class PublicPlanBuilder extends BaseBuilder<PublicPlan, PlanEntity> {
FieldSet otherPlanVersionsFields = fields.extractPrefixed(this.asPrefix(PublicPlan._otherPlanVersions));
Map<UUID, List<PublicPlan>> otherPlanVersionsMap = this.collectOtherPlanVersions(otherPlanVersionsFields, data);
FieldSet planStatusFields = fields.extractPrefixed(this.asPrefix(PublicPlan._status));
Map<UUID, PublicPlanStatus> planStatusItemsMap = this.collectPlanStatuses(planStatusFields, data);
for (PlanEntity d : data) {
PublicPlan m = new PublicPlan();
if (fields.hasField(this.asIndexer(PublicPlan._id))) m.setId(d.getId());
@ -80,7 +83,7 @@ public class PublicPlanBuilder extends BaseBuilder<PublicPlan, PlanEntity> {
if (fields.hasField(this.asIndexer(PublicPlan._finalizedAt))) m.setFinalizedAt(d.getFinalizedAt());
if (fields.hasField(this.asIndexer(PublicPlan._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
if (fields.hasField(this.asIndexer(PublicPlan._accessType))) m.setAccessType(d.getAccessType());
if (fields.hasField(this.asIndexer(PublicPlan._status))) m.setStatus(d.getStatus());
if (!planStatusFields.isEmpty() && planStatusItemsMap != null && planStatusItemsMap.containsKey(d.getStatusId())) m.setStatus(planStatusItemsMap.get(d.getStatusId()));
if (fields.hasField(this.asIndexer(PublicPlan._groupId))) m.setGroupId(d.getGroupId());
if (fields.hasField(this.asIndexer(PublicPlan._accessType))) m.setAccessType(d.getAccessType());
@ -190,4 +193,34 @@ public class PublicPlanBuilder extends BaseBuilder<PublicPlan, PlanEntity> {
return itemMap;
}
private Map<UUID, PublicPlanStatus> collectPlanStatuses(FieldSet fields, List<PlanEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty())
return null;
this.logger.debug("checking related - {}", PublicPlanStatus.class.getSimpleName());
Map<UUID, PublicPlanStatus> itemMap;
if (!fields.hasOtherField(this.asIndexer(PublicPlanStatus._id))) {
itemMap = this.asEmpty(
data.stream().map(PlanEntity::getStatusId).distinct().collect(Collectors.toList()),
x -> {
PublicPlanStatus item = new PublicPlanStatus();
item.setId(x);
return item;
},
PublicPlanStatus::getId);
} else {
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(PublicPlanStatus._id);
PlanStatusQuery q = this.queryFactory.query(PlanStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(PlanEntity::getStatusId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PublicPlanStatusBuilder.class).authorize(this.authorize).asForeignKey(q, clone, PublicPlanStatus::getId);
}
if (!fields.hasField(PublicPlanStatus._id)) {
itemMap.forEach((id, item) -> {
if (item != null)
item.setId(null);
});
}
return itemMap;
}
}

View File

@ -0,0 +1,68 @@
package org.opencdmp.model.builder;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.PlanStatusEntity;
import org.opencdmp.model.PublicPlanStatus;
import org.opencdmp.model.builder.planstatus.PlanStatusDefinitionBuilder;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PublicPlanStatusBuilder extends BaseBuilder<PublicPlanStatus, PlanStatusEntity> {
private final XmlHandlingService xmlHandlingService;
private final BuilderFactory builderFactory;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PublicPlanStatusBuilder(
ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicPlanStatusBuilder.class)));
this.xmlHandlingService = xmlHandlingService;
this.builderFactory = builderFactory;
}
public PublicPlanStatusBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
public List<PublicPlanStatus> build(FieldSet fields, List<PlanStatusEntity> data) throws MyApplicationException {
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
this.logger.trace(new DataLogEntry("requested fields", fields));
if (fields == null || data == null || fields.isEmpty())
return new ArrayList<>();
FieldSet definitionFields = fields.extractPrefixed(this.asPrefix(PublicPlanStatus._definition));
List<PublicPlanStatus> models = new ArrayList<>();
for (PlanStatusEntity d : data) {
PublicPlanStatus m = new PublicPlanStatus();
if (fields.hasField(this.asIndexer(PublicPlanStatus._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(PublicPlanStatus._name))) m.setName(d.getName());
if (fields.hasField(this.asIndexer(PublicPlanStatus._internalStatus))) m.setInternalStatus(d.getInternalStatus());
if (!definitionFields.isEmpty() && d.getDefinition() != null) {
PlanStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(PlanStatusDefinitionEntity.class, d.getDefinition());
m.setDefinition(this.builderFactory.builder(PublicPlanStatusDefinitionBuilder.class).authorize(this.authorize).build(definitionFields, definition));
}
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
}

View File

@ -0,0 +1,50 @@
package org.opencdmp.model.builder;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.model.PublicPlanStatusDefinition;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PublicPlanStatusDefinitionBuilder extends BaseBuilder<PublicPlanStatusDefinition, PlanStatusDefinitionEntity> {
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PublicPlanStatusDefinitionBuilder(
ConventionService conventionService) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicPlanStatusDefinitionBuilder.class)));
}
public PublicPlanStatusDefinitionBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
public List<PublicPlanStatusDefinition> build(FieldSet fields, List<PlanStatusDefinitionEntity> data) throws MyApplicationException {
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
this.logger.trace(new DataLogEntry("requested fields", fields));
if (fields == null || data == null || fields.isEmpty())
return new ArrayList<>();
List<PublicPlanStatusDefinition> models = new ArrayList<>();
for (PlanStatusDefinitionEntity d : data) {
PublicPlanStatusDefinition m = new PublicPlanStatusDefinition();
if (fields.hasField(this.asIndexer(PublicPlanStatusDefinition._availableActions))) m.setAvailableActions(d.getAvailableActions());
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
}

View File

@ -78,7 +78,7 @@ public class PlanUserCommonModelBuilder extends BaseCommonModelBuilder<PlanUserM
this.logger.debug("checking related - {}", UserModel.class.getSimpleName());
Map<UUID, UserModel> itemMap;
UserQuery q = this.queryFactory.query(UserQuery.class).disableTracking().isActive(IsActive.Active).authorize(this.authorize).ids(data.stream().map(PlanUserEntity::getUserId).distinct().collect(Collectors.toList()));
UserQuery q = this.queryFactory.query(UserQuery.class).disableTracking().isActive(IsActive.Active).ids(data.stream().map(PlanUserEntity::getUserId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(UserCommonModelBuilder.class).authorize(this.authorize).asForeignKey(q, UserEntity::getId);
return itemMap;
}

View File

@ -8,6 +8,7 @@ import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commonmodels.enums.DescriptionStatus;
import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.description.DescriptionStatusModel;
import org.opencdmp.commonmodels.models.descriptiotemplate.DescriptionTemplateModel;
import org.opencdmp.commonmodels.models.plan.PlanModel;
import org.opencdmp.commons.JsonHandlingService;
@ -25,9 +26,7 @@ import org.opencdmp.model.builder.commonmodels.CommonModelBuilderItemResponse;
import org.opencdmp.model.builder.commonmodels.descriptiontemplate.DescriptionTemplateCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.plan.PlanCommonModelBuilder;
import org.opencdmp.model.descriptiontemplate.DescriptionTemplate;
import org.opencdmp.query.DescriptionTemplateQuery;
import org.opencdmp.query.PlanDescriptionTemplateQuery;
import org.opencdmp.query.PlanQuery;
import org.opencdmp.query.*;
import org.opencdmp.service.visibility.VisibilityService;
import org.opencdmp.service.visibility.VisibilityServiceImpl;
import org.slf4j.LoggerFactory;
@ -103,18 +102,15 @@ public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<Descri
Map<UUID, DefinitionEntity> definitionEntityMap = this.collectDescriptionTemplateDefinitions(data);
Map<UUID, UUID> planDescriptionTemplateSections = this.collectPlanDescriptionTemplateSections(data);
Map<UUID, DescriptionStatusModel> descriptionStatuses = this.collectDescriptionStatuses(data);
List<CommonModelBuilderItemResponse<DescriptionModel, DescriptionEntity>> models = new ArrayList<>();
for (DescriptionEntity d : data) {
DescriptionModel m = new DescriptionModel();
m.setId(d.getId());
m.setLabel(d.getLabel());
m.setDescription(d.getDescription());
switch (d.getStatus()){
case Finalized -> m.setStatus(DescriptionStatus.Finalized);
case Draft -> m.setStatus(DescriptionStatus.Draft);
case Canceled -> m.setStatus(DescriptionStatus.Canceled);
default -> throw new MyApplicationException("unrecognized type " + d.getStatus());
}
if (descriptionStatuses != null && d.getStatusId() != null && descriptionStatuses.containsKey(d.getStatusId())) m.setStatus(descriptionStatuses.get(d.getStatusId()));
m.setCreatedAt(d.getCreatedAt());
m.setDescription(d.getDescription());
if (plans != null && d.getPlanId() != null && plans.containsKey(d.getPlanId())) m.setPlan(plans.get(d.getPlanId()));
@ -197,7 +193,8 @@ public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<Descri
if (this.isPublic) {
try {
this.entityManager.disableTenantFilters();
q = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(data.stream().map(DescriptionEntity::getPlanId).distinct().collect(Collectors.toList())).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public);
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
q = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(data.stream().map(DescriptionEntity::getPlanId).distinct().collect(Collectors.toList())).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public);
itemMap = this.builderFactory.builder(PlanCommonModelBuilder.class).setRepositoryId(this.repositoryId).useSharedStorage(this.useSharedStorage).setDisableDescriptions(true).authorize(this.authorize).asForeignKey(q, PlanEntity::getId);
try {
this.entityManager.reloadTenantFilters();
@ -231,4 +228,16 @@ public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<Descri
return itemMap;
}
private Map<UUID, DescriptionStatusModel> collectDescriptionStatuses(List<DescriptionEntity> data) throws MyApplicationException {
if (data.isEmpty())
return null;
this.logger.debug("checking related - {}", DescriptionStatusModel.class.getSimpleName());
Map<UUID, DescriptionStatusModel> itemMap;
DescriptionStatusQuery q = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(DescriptionStatusCommonModelBuilder.class).authorize(this.authorize).asForeignKey(q, DescriptionStatusEntity::getId);
return itemMap;
}
}

View File

@ -0,0 +1,67 @@
package org.opencdmp.model.builder.commonmodels.description;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commonmodels.models.description.DescriptionStatusModel;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionStatusEntity;
import org.opencdmp.model.builder.commonmodels.BaseCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.CommonModelBuilderItemResponse;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DescriptionStatusCommonModelBuilder extends BaseCommonModelBuilder<DescriptionStatusModel, DescriptionStatusEntity> {
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public DescriptionStatusCommonModelBuilder(
ConventionService conventionService
) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(DescriptionStatusCommonModelBuilder.class)));
}
public DescriptionStatusCommonModelBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
protected List<CommonModelBuilderItemResponse<DescriptionStatusModel, DescriptionStatusEntity>> buildInternal(List<DescriptionStatusEntity> data) throws MyApplicationException {
this.logger.debug("building for {}", Optional.ofNullable(data).map(List::size).orElse(0));
if (data == null || data.isEmpty()) return new ArrayList<>();
List<CommonModelBuilderItemResponse<DescriptionStatusModel, DescriptionStatusEntity>> models = new ArrayList<>();
for (DescriptionStatusEntity d : data) {
DescriptionStatusModel m = new DescriptionStatusModel();
m.setId(d.getId());
m.setName(d.getName());
if (d.getInternalStatus() != null) {
switch (d.getInternalStatus()){
case Finalized -> m.setInternalStatus(org.opencdmp.commonmodels.enums.DescriptionStatus.Finalized);
case Draft -> m.setInternalStatus(org.opencdmp.commonmodels.enums.DescriptionStatus.Draft);
case Canceled -> m.setInternalStatus(org.opencdmp.commonmodels.enums.DescriptionStatus.Canceled);
default -> throw new MyApplicationException("unrecognized type " + d.getInternalStatus());
}
}
models.add(new CommonModelBuilderItemResponse<>(m, d));
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
}

View File

@ -15,6 +15,7 @@ import org.opencdmp.commonmodels.models.FileEnvelopeModel;
import org.opencdmp.commonmodels.models.UserModel;
import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.plan.PlanModel;
import org.opencdmp.commonmodels.models.plan.PlanStatusModel;
import org.opencdmp.commonmodels.models.planblueprint.PlanBlueprintModel;
import org.opencdmp.commonmodels.models.planreference.PlanReferenceModel;
import org.opencdmp.commons.JsonHandlingService;
@ -127,6 +128,7 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
Map<UUID, UserModel> creators = this.collectCreators(data);
Map<UUID, PlanBlueprintModel> planBlueprints = this.collectPlanBlueprints(data);
Map<UUID, DefinitionEntity> definitionEntityMap = this.collectPlanBlueprintDefinitions(data);
Map<UUID, PlanStatusModel> planStatuses = this.collectPlanStatuses(data);
for (PlanEntity d : data) {
PlanModel m = new PlanModel();
@ -137,11 +139,7 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
m.setFinalizedAt(d.getFinalizedAt());
m.setCreatedAt(d.getCreatedAt());
m.setLanguage(d.getLanguage());
switch (d.getStatus()){
case Finalized -> m.setStatus(PlanStatus.Finalized);
case Draft -> m.setStatus(PlanStatus.Draft);
default -> throw new MyApplicationException("unrecognized type " + d.getStatus());
}
if (planStatuses != null && !planStatuses.isEmpty() && d.getStatusId() != null && planStatuses.containsKey(d.getStatusId())) m.setStatus(planStatuses.get(d.getStatusId()));
if (entityDois != null && !entityDois.isEmpty() && entityDois.containsKey(d.getId())) m.setEntityDois(entityDois.get(d.getId()));
if (creators != null && !creators.isEmpty() && d.getCreatorId() != null && creators.containsKey(d.getCreatorId())) m.setCreator(creators.get(d.getCreatorId()));
if (planBlueprints != null && !planBlueprints.isEmpty() && d.getBlueprintId() != null && planBlueprints.containsKey(d.getBlueprintId())) m.setPlanBlueprint(planBlueprints.get(d.getBlueprintId()));
@ -194,8 +192,8 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
this.logger.debug("checking related - {}", PlanUser.class.getSimpleName());
Map<UUID, List<PlanUserModel>> itemMap;
PlanUserQuery query = this.queryFactory.query(PlanUserQuery.class).disableTracking().isActives(IsActive.Active).authorize(this.authorize).planIds(data.stream().map(PlanEntity::getId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PlanUserCommonModelBuilder.class).authorize(this.authorize).asMasterKey(query, PlanUserEntity::getPlanId);
PlanUserQuery query = this.queryFactory.query(PlanUserQuery.class).disableTracking().isActives(IsActive.Active).planIds(data.stream().map(PlanEntity::getId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PlanUserCommonModelBuilder.class).asMasterKey(query, PlanUserEntity::getPlanId);
return itemMap;
}
@ -219,7 +217,8 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
if (this.isPublic) {
try {
this.entityManager.disableTenantFilters();
query = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).planIds(data.stream().map(PlanEntity::getId).distinct().collect(Collectors.toList())).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).statuses(org.opencdmp.commons.enums.PlanStatus.Finalized).accessTypes(org.opencdmp.commons.enums.PlanAccessType.Public));
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(org.opencdmp.commons.enums.PlanStatus.Finalized).isActives(IsActive.Active);
query = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).planIds(data.stream().map(PlanEntity::getId).distinct().collect(Collectors.toList())).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(org.opencdmp.commons.enums.PlanAccessType.Public));
itemMap = this.builderFactory.builder(DescriptionCommonModelBuilder.class).setRepositoryId(this.repositoryId).useSharedStorage(this.useSharedStorage).isPublic(this.isPublic).authorize(this.authorize).asMasterKey(query, DescriptionEntity::getPlanId);
try {
this.entityManager.reloadTenantFilters();
@ -290,4 +289,15 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
return itemMap;
}
private Map<UUID, PlanStatusModel> collectPlanStatuses(List<PlanEntity> data) throws MyApplicationException {
if (data.isEmpty())
return null;
this.logger.debug("checking related - {}", PlanStatusModel.class.getSimpleName());
Map<UUID, PlanStatusModel> itemMap;
PlanStatusQuery q = this.queryFactory.query(PlanStatusQuery.class).isActives(IsActive.Active).authorize(this.authorize).ids(data.stream().filter(x-> x.getStatusId() != null).map(PlanEntity::getStatusId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PlanStatusCommonModelBuilder.class).authorize(this.authorize).asForeignKey(q, PlanStatusEntity::getId);
return itemMap;
}
}

View File

@ -0,0 +1,64 @@
package org.opencdmp.model.builder.commonmodels.plan;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commonmodels.models.plan.PlanStatusModel;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.PlanStatusEntity;
import org.opencdmp.model.builder.commonmodels.BaseCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.CommonModelBuilderItemResponse;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PlanStatusCommonModelBuilder extends BaseCommonModelBuilder<PlanStatusModel, PlanStatusEntity> {
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PlanStatusCommonModelBuilder(
ConventionService conventionService
) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PlanStatusCommonModelBuilder.class)));
}
public PlanStatusCommonModelBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
protected List<CommonModelBuilderItemResponse<PlanStatusModel, PlanStatusEntity>> buildInternal(List<PlanStatusEntity> data) throws MyApplicationException {
this.logger.debug("building for {}", Optional.ofNullable(data).map(List::size).orElse(0));
if (data == null || data.isEmpty()) return new ArrayList<>();
List<CommonModelBuilderItemResponse<PlanStatusModel, PlanStatusEntity>> models = new ArrayList<>();
for (PlanStatusEntity d : data) {
PlanStatusModel m = new PlanStatusModel();
m.setId(d.getId());
m.setName(d.getName());
if (d.getInternalStatus() != null) {
switch (d.getInternalStatus()){
case Finalized -> m.setInternalStatus(org.opencdmp.commonmodels.enums.PlanStatus.Finalized);
case Draft -> m.setInternalStatus(org.opencdmp.commonmodels.enums.PlanStatus.Draft);
default -> throw new MyApplicationException("unrecognized type " + d.getInternalStatus());
}
}
models.add(new CommonModelBuilderItemResponse<>(m, d));
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
}

View File

@ -13,12 +13,12 @@ import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.authorization.authorizationcontentresolver.AuthorizationContentResolver;
import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.types.description.PropertyDefinitionEntity;
import org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionEntity;
import org.opencdmp.data.DescriptionTemplateEntity;
import org.opencdmp.data.*;
import org.opencdmp.model.DescriptionTag;
import org.opencdmp.model.PlanDescriptionTemplate;
import org.opencdmp.model.builder.BaseBuilder;
@ -26,14 +26,19 @@ import org.opencdmp.model.builder.DescriptionTagBuilder;
import org.opencdmp.model.builder.PlanDescriptionTemplateBuilder;
import org.opencdmp.model.builder.UserBuilder;
import org.opencdmp.model.builder.descriptionreference.DescriptionReferenceBuilder;
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
import org.opencdmp.model.builder.descriptiontemplate.DescriptionTemplateBuilder;
import org.opencdmp.model.builder.plan.PlanBuilder;
import org.opencdmp.model.description.Description;
import org.opencdmp.model.descriptionreference.DescriptionReference;
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
import org.opencdmp.model.descriptiontemplate.DescriptionTemplate;
import org.opencdmp.model.plan.Plan;
import org.opencdmp.model.planstatus.PlanStatusDefinitionAuthorization;
import org.opencdmp.model.user.User;
import org.opencdmp.query.*;
import org.opencdmp.service.custompolicy.CustomPolicyService;
import org.opencdmp.service.descriptionstatus.DescriptionStatusService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -55,6 +60,8 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
private final AuthorizationService authorizationService;
private final AuthorizationContentResolver authorizationContentResolver;
private final TenantScope tenantScope;
private final CustomPolicyService customPolicyService;
private final DescriptionStatusService descriptionStatusService;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@ -62,7 +69,7 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
public DescriptionBuilder(
ConventionService conventionService,
QueryFactory queryFactory,
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService, AuthorizationService authorizationService, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope) {
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService, AuthorizationService authorizationService, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, CustomPolicyService customPolicyService, DescriptionStatusService descriptionStatusService) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(DescriptionBuilder.class)));
this.queryFactory = queryFactory;
this.builderFactory = builderFactory;
@ -71,6 +78,8 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
this.authorizationService = authorizationService;
this.authorizationContentResolver = authorizationContentResolver;
this.tenantScope = tenantScope;
this.customPolicyService = customPolicyService;
this.descriptionStatusService = descriptionStatusService;
}
public DescriptionBuilder authorize(EnumSet<AuthorizationFlags> values) {
@ -85,6 +94,12 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
if (fields == null || data == null || fields.isEmpty())
return new ArrayList<>();
FieldSet statusFields = fields.extractPrefixed(this.asPrefix(Description._status));
Map<UUID, DescriptionStatus> statusItemsMap = this.collectDescriptionStatuses(statusFields, data);
FieldSet availableStatusesFields = fields.extractPrefixed(this.asPrefix(Description._availableStatuses));
Map<UUID, List<DescriptionStatus>> avaialbleStatusesItemsMap = this.collectAvailableDescriptionStatuses(availableStatusesFields, data);
FieldSet planDescriptionTemplateFields = fields.extractPrefixed(this.asPrefix(Description._planDescriptionTemplate));
Map<UUID, PlanDescriptionTemplate> planDescriptionTemplateItemsMap = this.collectPlanDescriptionTemplates(planDescriptionTemplateFields, data);
@ -110,13 +125,15 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
Set<String> authorizationFlags = this.extractAuthorizationFlags(fields, Description._authorizationFlags, this.authorizationContentResolver.getPermissionNames());
Map<UUID, AffiliatedResource> affiliatedResourceMap = authorizationFlags == null || authorizationFlags.isEmpty() ? null : this.authorizationContentResolver.descriptionsAffiliation(data.stream().map(DescriptionEntity::getId).collect(Collectors.toList()));
FieldSet statusAuthorizationFlags = fields.extractPrefixed(this.asPrefix(Description._statusAuthorizationFlags));
List<Description> models = new ArrayList<>();
for (DescriptionEntity d : data) {
Description m = new Description();
if (fields.hasField(this.asIndexer(Description._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(Description._tenantId))) m.setTenantId(d.getTenantId());
if (fields.hasField(this.asIndexer(Description._label))) m.setLabel(d.getLabel());
if (fields.hasField(this.asIndexer(Description._status))) m.setStatus(d.getStatus());
if (!statusFields.isEmpty() && statusItemsMap != null && statusItemsMap.containsKey(d.getStatusId())) m.setStatus(statusItemsMap.get(d.getStatusId()));
if (avaialbleStatusesItemsMap != null && !avaialbleStatusesItemsMap.isEmpty() && avaialbleStatusesItemsMap.containsKey(d.getId())) m.setAvailableStatuses(avaialbleStatusesItemsMap.get(d.getId()));
if (fields.hasField(this.asIndexer(Description._description))) m.setDescription(d.getDescription());
if (fields.hasField(this.asIndexer(Description._createdAt))) m.setCreatedAt(d.getCreatedAt());
if (fields.hasField(this.asIndexer(Description._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
@ -135,6 +152,9 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
m.setProperties(this.builderFactory.builder(PropertyDefinitionBuilder.class).withDefinition(definitionEntityMap != null ? definitionEntityMap.getOrDefault(d.getDescriptionTemplateId(), null) : null).authorize(this.authorize).build(definitionPropertiesFields, propertyDefinition));
}
if (affiliatedResourceMap != null && !authorizationFlags.isEmpty()) m.setAuthorizationFlags(this.evaluateAuthorizationFlags(this.authorizationService, authorizationFlags, affiliatedResourceMap.getOrDefault(d.getId(), null)));
if (!statusAuthorizationFlags.isEmpty() && !this.conventionService.isListNullOrEmpty(m.getAvailableStatuses())) {
m.setStatusAuthorizationFlags(this.evaluateStatusAuthorizationFlags(this.authorizationService, statusAuthorizationFlags, d));
}
models.add(m);
}
@ -143,6 +163,58 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
return models;
}
private Map<UUID, DescriptionStatus> collectDescriptionStatuses(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty())
return null;
this.logger.debug("checking related - {}", DescriptionStatus.class.getSimpleName());
Map<UUID, DescriptionStatus> itemMap;
if (!fields.hasOtherField(this.asIndexer(DescriptionStatus._id))) {
itemMap = this.asEmpty(
data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()),
x -> {
DescriptionStatus item = new DescriptionStatus();
item.setId(x);
return item;
},
DescriptionStatus::getId);
} else {
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(DescriptionStatus._id);
DescriptionStatusQuery q = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(DescriptionStatusBuilder.class).authorize(this.authorize).asForeignKey(q, clone, DescriptionStatus::getId);
}
if (!fields.hasField(DescriptionStatus._id)) {
itemMap.forEach((id, item) -> {
if (item != null)
item.setId(null);
});
}
return itemMap;
}
private Map<UUID, List<DescriptionStatus>> collectAvailableDescriptionStatuses(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty()) return null;
this.logger.debug("checking related - {}", DescriptionStatus.class.getSimpleName());
Map<UUID, List<DescriptionStatus>> itemMap = new HashMap<>();
FieldSet fieldSet = new BaseFieldSet(fields.getFields()).ensure(DescriptionStatus._id);
Map<UUID, List<UUID>> itemStatusIdsMap = this.descriptionStatusService.getAuthorizedAvailableStatusIds(data.stream().map(DescriptionEntity::getId).collect(Collectors.toList()));
List<DescriptionStatusEntity> statusEntities = this.queryFactory.query(DescriptionStatusQuery.class).authorize(this.authorize).isActive(IsActive.Active).ids(itemStatusIdsMap.values().stream().flatMap(List::stream).distinct().collect(Collectors.toList())).collectAs(fieldSet);
List<DescriptionStatus> descriptionStatuses = this.builderFactory.builder(DescriptionStatusBuilder.class).authorize(this.authorize).build(fieldSet, statusEntities);
for (DescriptionEntity entity: data) {
itemMap.put(entity.getId(), new ArrayList<>());
List<UUID> statusIds = itemStatusIdsMap.getOrDefault(entity.getId(), new ArrayList<>());
for (UUID statusId: statusIds) {
itemMap.get(entity.getId()).addAll(descriptionStatuses.stream().filter(x -> x.getId().equals(statusId)).collect(Collectors.toList()));
}
}
return itemMap;
}
private Map<UUID, User> collectUsers(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty())
return null;
@ -315,4 +387,22 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
return itemMap;
}
private List<String> evaluateStatusAuthorizationFlags(AuthorizationService authorizationService, FieldSet statusAuthorizationFlags, DescriptionEntity description) {
List<String> allowed = new ArrayList<>();
if (statusAuthorizationFlags == null) return allowed;
if (authorizationService == null) return allowed;
if (description == null) return allowed;
String editPermission = this.customPolicyService.getDescriptionStatusCanEditStatusPermission(description.getStatusId());
AffiliatedResource affiliatedResource = this.authorizationContentResolver.planAffiliation(description.getPlanId());
for (String permission : statusAuthorizationFlags.getFields()) {
if (statusAuthorizationFlags.hasField(this.asIndexer(PlanStatusDefinitionAuthorization._edit))) {
Boolean isAllowed = affiliatedResource == null ? this.authorizationService.authorize(editPermission) : this.authorizationService.authorizeAtLeastOne(List.of(affiliatedResource), editPermission);
if (isAllowed) allowed.add(permission);
}
}
return allowed;
}
}

View File

@ -56,6 +56,7 @@ public class DescriptionStatusBuilder extends BaseBuilder<DescriptionStatus, Des
if (fields.hasField(this.asIndexer(DescriptionStatus._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(DescriptionStatus._name))) m.setName(d.getName());
if (fields.hasField(this.asIndexer(DescriptionStatus._description))) m.setDescription(d.getDescription());
if (fields.hasField(this.asIndexer(DescriptionStatus._action))) m.setAction(d.getAction());
if (fields.hasField(this.asIndexer(DescriptionStatus._updatedAt))) m.setUpdateAt(d.getUpdatedAt());
if (fields.hasField(this.asIndexer(DescriptionStatus._createdAt))) m.setCreatedAt(d.getCreatedAt());
if (fields.hasField(this.asIndexer(DescriptionStatus._isActive))) m.setIsActive(d.getIsActive());

View File

@ -50,6 +50,7 @@ public class DescriptionStatusDefinitionBuilder extends BaseBuilder<DescriptionS
if (!authorizationFields.isEmpty() && d.getAuthorization() != null) {
m.setAuthorization(this.builderFactory.builder(DescriptionStatusDefinitionAuthorizationBuilder.class).authorize(authorize).build(authorizationFields, d.getAuthorization()));
}
if (fields.hasField(this.asIndexer(DescriptionStatusDefinition._availableActions))) m.setAvailableActions(d.getAvailableActions());
models.add(m);
}

View File

@ -14,12 +14,14 @@ import org.opencdmp.authorization.authorizationcontentresolver.AuthorizationCont
import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.EntityType;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.types.plan.PlanPropertiesEntity;
import org.opencdmp.commons.types.planblueprint.DefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.PlanBlueprintEntity;
import org.opencdmp.data.PlanEntity;
import org.opencdmp.data.PlanStatusEntity;
import org.opencdmp.model.PlanDescriptionTemplate;
import org.opencdmp.model.PlanUser;
import org.opencdmp.model.EntityDoi;
@ -27,12 +29,17 @@ import org.opencdmp.model.builder.*;
import org.opencdmp.model.builder.description.DescriptionBuilder;
import org.opencdmp.model.builder.planblueprint.PlanBlueprintBuilder;
import org.opencdmp.model.builder.planreference.PlanReferenceBuilder;
import org.opencdmp.model.builder.planstatus.PlanStatusBuilder;
import org.opencdmp.model.description.Description;
import org.opencdmp.model.plan.Plan;
import org.opencdmp.model.planblueprint.PlanBlueprint;
import org.opencdmp.model.planreference.PlanReference;
import org.opencdmp.model.planstatus.PlanStatus;
import org.opencdmp.model.planstatus.PlanStatusDefinitionAuthorization;
import org.opencdmp.model.user.User;
import org.opencdmp.query.*;
import org.opencdmp.service.custompolicy.CustomPolicyService;
import org.opencdmp.service.planstatus.PlanStatusService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -54,13 +61,15 @@ public class PlanBuilder extends BaseBuilder<Plan, PlanEntity> {
private final AuthorizationService authorizationService;
private final AuthorizationContentResolver authorizationContentResolver;
private final TenantScope tenantScope;
private final CustomPolicyService customPolicyService;
private final PlanStatusService planStatusService;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PlanBuilder(ConventionService conventionService,
QueryFactory queryFactory,
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService, AuthorizationService authorizationService, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope) {
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService, AuthorizationService authorizationService, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, CustomPolicyService customPolicyService, PlanStatusService planStatusService) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PlanBuilder.class)));
this.queryFactory = queryFactory;
this.builderFactory = builderFactory;
@ -69,6 +78,8 @@ public class PlanBuilder extends BaseBuilder<Plan, PlanEntity> {
this.authorizationService = authorizationService;
this.authorizationContentResolver = authorizationContentResolver;
this.tenantScope = tenantScope;
this.customPolicyService = customPolicyService;
this.planStatusService = planStatusService;
}
public PlanBuilder authorize(EnumSet<AuthorizationFlags> values) {
@ -85,6 +96,12 @@ public class PlanBuilder extends BaseBuilder<Plan, PlanEntity> {
List<Plan> models = new ArrayList<>();
FieldSet statusFields = fields.extractPrefixed(this.asPrefix(Plan._status));
Map<UUID, PlanStatus> statusItemsMap = this.collectPlanStatuses(statusFields, data);
FieldSet availableStatusesFields = fields.extractPrefixed(this.asPrefix(Plan._availableStatuses));
Map<UUID, List<PlanStatus>> avaialbleStatusesItemsMap = this.collectAvailablePlanStatuses(availableStatusesFields, data);
FieldSet entityDoisFields = fields.extractPrefixed(this.asPrefix(Plan._entityDois));
Map<UUID, List<EntityDoi>> entityDoisMap = this.collectEntityDois(entityDoisFields, data);
@ -115,13 +132,15 @@ public class PlanBuilder extends BaseBuilder<Plan, PlanEntity> {
Set<String> authorizationFlags = this.extractAuthorizationFlags(fields, Plan._authorizationFlags, this.authorizationContentResolver.getPermissionNames());
Map<UUID, AffiliatedResource> affiliatedResourceMap = authorizationFlags == null || authorizationFlags.isEmpty() ? null : this.authorizationContentResolver.plansAffiliation(data.stream().map(PlanEntity::getId).collect(Collectors.toList()));
FieldSet statusAuthorizationFlags = fields.extractPrefixed(this.asPrefix(Plan._statusAuthorizationFlags));
for (PlanEntity d : data) {
Plan m = new Plan();
if (fields.hasField(this.asIndexer(Plan._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(Plan._tenantId))) m.setTenantId(d.getTenantId());
if (fields.hasField(this.asIndexer(Plan._label))) m.setLabel(d.getLabel());
if (fields.hasField(this.asIndexer(Plan._version))) m.setVersion(d.getVersion());
if (fields.hasField(this.asIndexer(Plan._status))) m.setStatus(d.getStatus());
if (!statusFields.isEmpty() && statusItemsMap != null && statusItemsMap.containsKey(d.getStatusId())) m.setStatus(statusItemsMap.get(d.getStatusId()));
if (avaialbleStatusesItemsMap != null && !avaialbleStatusesItemsMap.isEmpty() && avaialbleStatusesItemsMap.containsKey(d.getId())) m.setAvailableStatuses(avaialbleStatusesItemsMap.get(d.getId()));
if (fields.hasField(this.asIndexer(Plan._groupId))) m.setGroupId(d.getGroupId());
if (fields.hasField(this.asIndexer(Plan._description))) m.setDescription(d.getDescription());
if (fields.hasField(this.asIndexer(Plan._createdAt))) m.setCreatedAt(d.getCreatedAt());
@ -150,6 +169,9 @@ public class PlanBuilder extends BaseBuilder<Plan, PlanEntity> {
m.setProperties(this.builderFactory.builder(PlanPropertiesBuilder.class).withDefinition(definitionEntityMap != null ? definitionEntityMap.getOrDefault(d.getBlueprintId(), null) : null).authorize(this.authorize).build(planPropertiesFields, propertyDefinition));
}
if (affiliatedResourceMap != null && !authorizationFlags.isEmpty()) m.setAuthorizationFlags(this.evaluateAuthorizationFlags(this.authorizationService, authorizationFlags, affiliatedResourceMap.getOrDefault(d.getId(), null)));
if (!statusAuthorizationFlags.isEmpty() && !this.conventionService.isListNullOrEmpty(m.getAvailableStatuses())) {
m.setStatusAuthorizationFlags(this.evaluateStatusAuthorizationFlags(this.authorizationService, statusAuthorizationFlags, d));
}
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
@ -157,6 +179,58 @@ public class PlanBuilder extends BaseBuilder<Plan, PlanEntity> {
return models;
}
private Map<UUID, PlanStatus> collectPlanStatuses(FieldSet fields, List<PlanEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty())
return null;
this.logger.debug("checking related - {}", PlanStatus.class.getSimpleName());
Map<UUID, PlanStatus> itemMap;
if (!fields.hasOtherField(this.asIndexer(PlanStatus._id))) {
itemMap = this.asEmpty(
data.stream().map(PlanEntity::getStatusId).distinct().collect(Collectors.toList()),
x -> {
PlanStatus item = new PlanStatus();
item.setId(x);
return item;
},
PlanStatus::getId);
} else {
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(PlanStatus._id);
PlanStatusQuery q = this.queryFactory.query(PlanStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(PlanEntity::getStatusId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PlanStatusBuilder.class).authorize(this.authorize).asForeignKey(q, clone, PlanStatus::getId);
}
if (!fields.hasField(PlanStatus._id)) {
itemMap.forEach((id, item) -> {
if (item != null)
item.setId(null);
});
}
return itemMap;
}
private Map<UUID, List<PlanStatus>> collectAvailablePlanStatuses(FieldSet fields, List<PlanEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty()) return null;
this.logger.debug("checking related - {}", PlanStatus.class.getSimpleName());
Map<UUID, List<PlanStatus>> itemMap = new HashMap<>();
FieldSet fieldSet = new BaseFieldSet(fields.getFields()).ensure(PlanStatus._id);
Map<UUID, List<UUID>> itemStatusIdsMap = this.planStatusService.getAuthorizedAvailableStatusIds(data.stream().map(PlanEntity::getId).collect(Collectors.toList()));
List<PlanStatusEntity> statusEntities = this.queryFactory.query(PlanStatusQuery.class).authorize(this.authorize).isActives(IsActive.Active).ids(itemStatusIdsMap.values().stream().flatMap(List::stream).distinct().collect(Collectors.toList())).collectAs(fieldSet);
List<PlanStatus> planStatuses = this.builderFactory.builder(PlanStatusBuilder.class).authorize(this.authorize).build(fieldSet, statusEntities);
for (PlanEntity entity: data) {
itemMap.put(entity.getId(), new ArrayList<>());
List<UUID> statusIds = itemStatusIdsMap.getOrDefault(entity.getId(), new ArrayList<>());
for (UUID statusId: statusIds) {
itemMap.get(entity.getId()).addAll(planStatuses.stream().filter(x -> x.getId().equals(statusId)).collect(Collectors.toList()));
}
}
return itemMap;
}
private Map<UUID, List<PlanReference>> collectPlanReferences(FieldSet fields, List<PlanEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty()) return null;
this.logger.debug("checking related - {}", PlanReference.class.getSimpleName());
@ -342,4 +416,22 @@ public class PlanBuilder extends BaseBuilder<Plan, PlanEntity> {
return itemMap;
}
private List<String> evaluateStatusAuthorizationFlags(AuthorizationService authorizationService, FieldSet statusAuthorizationFlags, PlanEntity plan) {
List<String> allowed = new ArrayList<>();
if (statusAuthorizationFlags == null) return allowed;
if (authorizationService == null) return allowed;
if (plan == null) return allowed;
String editPermission = this.customPolicyService.getPlanStatusCanEditStatusPermission(plan.getStatusId());
AffiliatedResource affiliatedResource = this.authorizationContentResolver.planAffiliation(plan.getId());
for (String permission : statusAuthorizationFlags.getFields()) {
if (statusAuthorizationFlags.hasField(this.asIndexer(PlanStatusDefinitionAuthorization._edit))) {
Boolean isAllowed = affiliatedResource == null ? this.authorizationService.authorize(editPermission) : this.authorizationService.authorizeAtLeastOne(List.of(affiliatedResource), editPermission);
if (isAllowed) allowed.add(permission);
}
}
return allowed;
}
}

View File

@ -68,6 +68,8 @@ public class PlanStatusBuilder extends BaseBuilder<PlanStatus, PlanStatusEntity>
m.setIsActive(d.getIsActive());
if (fields.hasField(this.asIndexer(PlanStatus._description)))
m.setDescription(d.getDescription());
if (fields.hasField(this.asIndexer(PlanStatus._action)))
m.setAction(d.getAction());
if (fields.hasField(this.asIndexer(PlanStatus._internalStatus)))
m.setInternalStatus(d.getInternalStatus());
if (fields.hasField(this.asIndexer(PlanStatus._hash)))

View File

@ -53,6 +53,8 @@ public class PlanStatusDefinitionBuilder extends BaseBuilder<PlanStatusDefinitio
m.setAuthorization(this.builderFactory.builder(PlanStatusDefinitionAuthorizationBuilder.class).authorize(this.authorize).build(authorizationFields, d.getAuthorization()));
}
if (fields.hasField(this.asIndexer(PlanStatusDefinition._availableActions))) m.setAvailableActions(d.getAvailableActions());
models.add(m);
}

View File

@ -1,6 +1,6 @@
package org.opencdmp.model.description;
import org.opencdmp.commons.enums.DescriptionStatus;
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.model.*;
import org.opencdmp.model.descriptionreference.DescriptionReference;
@ -86,6 +86,12 @@ public class Description {
public static final String _plan = "plan";
private List<DescriptionStatus> availableStatuses;
public static final String _availableStatuses = "availableStatuses";
private List<String> statusAuthorizationFlags;
public static final String _statusAuthorizationFlags = "statusAuthorizationFlags";
private Boolean belongsToCurrentTenant;
public static final String _belongsToCurrentTenant = "belongsToCurrentTenant";
@ -231,6 +237,22 @@ public class Description {
this.authorizationFlags = authorizationFlags;
}
public List<DescriptionStatus> getAvailableStatuses() {
return availableStatuses;
}
public void setAvailableStatuses(List<DescriptionStatus> availableStatuses) {
this.availableStatuses = availableStatuses;
}
public List<String> getStatusAuthorizationFlags() {
return statusAuthorizationFlags;
}
public void setStatusAuthorizationFlags(List<String> statusAuthorizationFlags) {
this.statusAuthorizationFlags = statusAuthorizationFlags;
}
public Boolean getBelongsToCurrentTenant() {
return belongsToCurrentTenant;
}

View File

@ -16,6 +16,9 @@ public class DescriptionStatus {
public final static String _description = "description";
private String description;
public static final String _action = "action";
private String action;
public final static String _createdAt = "createdAt";
private Instant createdAt;
@ -46,6 +49,14 @@ public class DescriptionStatus {
public String getDescription() { return this.description; }
public void setDescription(String description) { this.description = description; }
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public Instant getCreatedAt() { return this.createdAt; }
public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; }

View File

@ -1,11 +1,26 @@
package org.opencdmp.model.descriptionstatus;
import org.opencdmp.commons.enums.DescriptionStatusAvailableActionType;
import java.util.List;
public class DescriptionStatusDefinition {
public final static String _authorization = "authorization";
private DescriptionStatusDefinitionAuthorization authorization;
public final static String _availableActions = "availableActions";
private List<DescriptionStatusAvailableActionType> availableActions;
public DescriptionStatusDefinitionAuthorization getAuthorization() { return this.authorization; }
public void setAuthorization(DescriptionStatusDefinitionAuthorization authorization) { this.authorization = authorization; }
public List<DescriptionStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<DescriptionStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
}

View File

@ -30,7 +30,7 @@ public class DescriptionToPublicApiDatasetMapper {
model.setDescription(description.getDescription());
model.setReference("");
model.setUri("");
model.setStatus(description.getStatus());
// TODO status model.setStatus(description.getStatus());
model.setDmp(dmp);
model.setDatasetProfileDefinition(descriptionTemplateToPublicApiDatasetProfileMapper.toPublicModel(description.getDescriptionTemplate()));

View File

@ -46,9 +46,9 @@ public class DescriptionPersist {
public static final String _descriptionTemplateId = "descriptionTemplateId";
private DescriptionStatus status;
private UUID statusId;
public static final String _status = "status";
public static final String _statusId = "statusId";
private String description;
@ -97,12 +97,12 @@ public class DescriptionPersist {
this.planDescriptionTemplateId = planDescriptionTemplateId;
}
public DescriptionStatus getStatus() {
return this.status;
public UUID getStatusId() {
return statusId;
}
public void setStatus(DescriptionStatus status) {
this.status = status;
public void setStatusId(UUID statusId) {
this.statusId = statusId;
}
public String getDescription() {
@ -178,16 +178,19 @@ public class DescriptionPersist {
DescriptionTemplateEntity descriptionTemplate = null;
PlanEntity planEntity = null;
PlanBlueprintEntity planBlueprintEntity = null;
DescriptionStatusEntity statusEntity = null;
try {
descriptionTemplate = this.isValidGuid(item.getDescriptionTemplateId()) ? this.entityManager.find(DescriptionTemplateEntity.class, item.getDescriptionTemplateId(), true) : null;
planEntity = this.isValidGuid(item.getPlanId()) ? this.entityManager.find(PlanEntity.class, item.getPlanId(), true) : null;
planBlueprintEntity = planEntity == null ? null : this.entityManager.find(PlanBlueprintEntity.class, planEntity.getBlueprintId());
statusEntity = this.isValidGuid(item.getStatusId()) ? this.entityManager.find(DescriptionStatusEntity.class, item.getStatusId(), true) : null;
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
DefinitionEntity definition = descriptionTemplate == null ? null : this.xmlHandlingService.fromXmlSafe(DefinitionEntity.class, descriptionTemplate.getDefinition());
PlanBlueprintEntity finalPlanBlueprintEntity = planBlueprintEntity;
DescriptionStatusEntity finalStatusEntity = statusEntity;
return Arrays.asList(
this.spec()
.iff(() -> this.isValidGuid(item.getId()))
@ -214,21 +217,22 @@ public class DescriptionPersist {
.must(() -> this.isValidGuid(item.getPlanDescriptionTemplateId()))
.failOn(DescriptionPersist._planDescriptionTemplateId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._planDescriptionTemplateId}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isNull(item.getStatus()))
.failOn(DescriptionPersist._status).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._status}, LocaleContextHolder.getLocale())),
.iff(() -> this.isValidGuid(item.getId()))
.must(() -> this.isValidGuid(item.getStatusId()))
.failOn(DescriptionPersist._statusId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._statusId}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == DescriptionStatus.Finalized)
.must(() -> !this.isNull(item.getProperties()))
.failOn(DescriptionPersist._properties).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._properties}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == DescriptionStatus.Finalized)
.must(() -> this.isDescriptionTemplateMaxMultiplicityValid(finalPlanBlueprintEntity, item.getPlanId(), item.getPlanDescriptionTemplateId(), this.isValidGuid(item.getId())))
.failOn(DescriptionPersist._descriptionTemplateId).failWith(this.messageSource.getMessage("Validation.InvalidDescriptionTemplateMultiplicity", new Object[]{DescriptionPersist._descriptionTemplateId}, LocaleContextHolder.getLocale())),
this.refSpec()
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == DescriptionStatus.Finalized)
.on(DescriptionPersist._properties)
.over(item.getProperties())
.using(() -> this.validatorFactory.validator(PropertyDefinitionPersist.PropertyDefinitionPersistValidator.class).setStatus(item.getStatus()).withDefinition(definition).setVisibilityService(definition, item.getProperties()))
.using(() -> this.validatorFactory.validator(PropertyDefinitionPersist.PropertyDefinitionPersistValidator.class).setStatus(finalStatusEntity.getInternalStatus()).withDefinition(definition).setVisibilityService(definition, item.getProperties()))
// this.navSpec()
// .iff(() -> !this.isNull(item.getTags()))
// .on(DescriptionPersist._tags)

View File

@ -1,6 +1,5 @@
package org.opencdmp.model.persist;
import org.opencdmp.commons.enums.DescriptionStatus;
import org.opencdmp.commons.validation.BaseValidator;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.convention.ConventionService;
@ -21,7 +20,7 @@ public class DescriptionStatusPersist {
public static final String _id = "id";
private DescriptionStatus status;
private UUID statusId;
public static final String _status = "status";
@ -37,12 +36,12 @@ public class DescriptionStatusPersist {
this.id = id;
}
public DescriptionStatus getStatus() {
return status;
public UUID getStatusId() {
return statusId;
}
public void setStatus(DescriptionStatus status) {
this.status = status;
public void setStatusId(UUID statusId) {
this.statusId = statusId;
}
public String getHash() {
@ -82,7 +81,7 @@ public class DescriptionStatusPersist {
.must(() -> this.isValidHash(item.getHash()))
.failOn(DescriptionStatusPersist._hash).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._hash}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isNull(item.getStatus()))
.must(() -> this.isValidGuid(item.getStatusId()))
.failOn(DescriptionStatusPersist._status).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._status}, LocaleContextHolder.getLocale()))
);
}

View File

@ -36,9 +36,9 @@ public class PlanPersist {
public static final String _label = "label";
private PlanStatus status;
private UUID statusId;
public static final String _status = "status";
public static final String _statusId = "statusId";
private PlanPropertiesPersist properties;
@ -84,12 +84,12 @@ public class PlanPersist {
this.label = label;
}
public PlanStatus getStatus() {
return this.status;
public UUID getStatusId() {
return statusId;
}
public void setStatus(PlanStatus status) {
this.status = status;
public void setStatusId(UUID statusId) {
this.statusId = statusId;
}
public PlanPropertiesPersist getProperties() {
@ -186,9 +186,10 @@ public class PlanPersist {
@Override
protected List<Specification> specifications(PlanPersist item) {
PlanBlueprintEntity planBlueprintEntity = null;
PlanStatusEntity statusEntity = null;
try {
planBlueprintEntity = this.isValidGuid(item.getBlueprint()) ? this.entityManager.find(PlanBlueprintEntity.class, item.getBlueprint(), true) : null;
statusEntity = this.isValidGuid(item.getStatusId()) ? this.entityManager.find(PlanStatusEntity.class, item.getStatusId(), true) : null;
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
@ -203,6 +204,7 @@ public class PlanPersist {
accessFieldLabel = this.getSystemFieldLabel(definition, PlanBlueprintSystemFieldType.AccessRights);
}
PlanStatusEntity finalStatusEntity = statusEntity;
return Arrays.asList(
this.spec()
.iff(() -> this.isValidGuid(item.getId()))
@ -220,40 +222,41 @@ public class PlanPersist {
.must(() -> this.lessEqualLength(item.getLabel(), PlanEntity._labelLength))
.failOn(PlanPersist._label).failWith(this.messageSource.getMessage("Validation_MaxLength", new Object[]{PlanPersist._label}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == PlanStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == PlanStatus.Finalized)
.must(() -> !this.isEmpty(item.getDescription()))
.failOn(PlanPersist._description).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{PlanPersist._description}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isNull(item.getStatus()))
.failOn(PlanPersist._status).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{PlanPersist._status}, LocaleContextHolder.getLocale())),
.iff(() -> this.isValidGuid(item.getId()))
.must(() -> !this.isNull(item.getStatusId()))
.failOn(PlanPersist._statusId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{PlanPersist._statusId}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == PlanStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == PlanStatus.Finalized)
.must(() -> this.isValidGuid(item.getBlueprint()))
.failOn(PlanPersist._blueprint).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{PlanPersist._blueprint}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == PlanStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == PlanStatus.Finalized)
.must(() -> !this.isNull(item.getProperties()))
.failOn(PlanPersist._properties).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{PlanPersist._properties}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == PlanStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == PlanStatus.Finalized)
.must(() -> this.isDescriptionTemplateMultiplicityValid(finalPlanBlueprintEntity, item.getId()))
.failOn(PlanPersist._descriptionTemplates).failWith(this.messageSource.getMessage("Validation.InvalidDescriptionTemplateMultiplicityOnPlan", new Object[]{PlanPersist._descriptionTemplates}, LocaleContextHolder.getLocale())),
this.refSpec()
.iff(() -> !this.isNull(item.getProperties()))
.iff(() -> !this.isNull(item.getProperties()) && finalStatusEntity != null)
.on(PlanPersist._properties)
.over(item.getProperties())
.using(() -> this.validatorFactory.validator(PlanPropertiesPersist.PlanPropertiesPersistValidator.class).setStatus(item.getStatus()).withDefinition(definition)),
.using(() -> this.validatorFactory.validator(PlanPropertiesPersist.PlanPropertiesPersistValidator.class).setStatus(finalStatusEntity.getInternalStatus()).withDefinition(definition)),
this.spec()
.iff(() -> item.getStatus() == PlanStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == PlanStatus.Finalized)
.must(() -> !this.isNull(item.getLanguage()))
.failOn(PlanPersist._language).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{languageFieldLabel != null ? languageFieldLabel : PlanBlueprintSystemFieldType.Language.name()}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == PlanStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == PlanStatus.Finalized)
.must(() -> !this.isNull(item.getAccessType()))
.failOn(PlanPersist._accessType).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{accessFieldLabel != null ? accessFieldLabel : PlanBlueprintSystemFieldType.AccessRights.name()}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getStatus() == PlanStatus.Finalized)
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == PlanStatus.Finalized)
.must(() -> !this.isListNullOrEmpty(item.getDescriptionTemplates()))
.failOn(PlanPersist._descriptionTemplates).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{PlanPersist._descriptionTemplates}, LocaleContextHolder.getLocale())),
this.navSpec()

View File

@ -62,11 +62,6 @@ public class DescriptionStatusDefinitionAuthorizationItemPersist {
@Override
protected List<Specification> specifications(DescriptionStatusDefinitionAuthorizationItemPersist item) {
return Arrays.asList(
this.spec()
.must(() -> !this.isListNullOrEmpty(item.getRoles()))
.failOn(PlanStatusDefinitionAuthorizationItemPersist._roles).failWith(messageSource.getMessage("Validation_Required", new Object[]{PlanStatusDefinitionAuthorizationItemPersist._roles}, LocaleContextHolder.getLocale())), this.spec()
.must(() -> !this.isListNullOrEmpty(item.getPlanRoles()))
.failOn(PlanStatusDefinitionAuthorizationItemPersist._planRoles).failWith(messageSource.getMessage("Validation_Required", new Object[]{PlanStatusDefinitionAuthorizationItemPersist._planRoles}, LocaleContextHolder.getLocale()))
);
}
}

View File

@ -2,10 +2,10 @@ package org.opencdmp.model.persist.descriptionstatus;
import gr.cite.tools.validation.ValidatorFactory;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.enums.DescriptionStatusAvailableActionType;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.model.descriptionstatus.DescriptionStatusDefinitionAuthorization;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
@ -20,9 +20,19 @@ public class DescriptionStatusDefinitionPersist {
private DescriptionStatusDefinitionAuthorizationPersist authorization;
public final static String _authorization = "authorization";
private List<DescriptionStatusAvailableActionType> availableActions;
public final static String _availableActions = "availableActions";
public DescriptionStatusDefinitionAuthorizationPersist getAuthorization() { return authorization; }
public void setAuthorization(DescriptionStatusDefinitionAuthorizationPersist authorization) { this.authorization = authorization; }
public List<DescriptionStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<DescriptionStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
@Component(DescriptionStatusDefinitionPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

View File

@ -27,6 +27,9 @@ public class DescriptionStatusPersist {
private String description;
public final static String _description = "description";
private String action;
public static final String _action = "action";
private org.opencdmp.commons.enums.DescriptionStatus internalStatus;
public final static String _internalStatus = "internalStatus";
@ -46,6 +49,14 @@ public class DescriptionStatusPersist {
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public org.opencdmp.commons.enums.DescriptionStatus getInternalStatus() { return internalStatus; }
public void setInternalStatus(org.opencdmp.commons.enums.DescriptionStatus internalStatus) { this.internalStatus = internalStatus; }
@ -93,6 +104,10 @@ public class DescriptionStatusPersist {
.iff(() -> !this.isEmpty(item.getName()))
.must(() -> this.lessEqualLength(item.getName(), DescriptionStatusEntity._nameLength))
.failOn(DescriptionStatusPersist._name).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._name}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isEmpty(item.getAction()))
.must(() -> this.lessEqualLength(item.getAction(), DescriptionStatusEntity._actionLength))
.failOn(DescriptionStatusPersist._action).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._action}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getInternalStatus() == org.opencdmp.commons.enums.DescriptionStatus.Finalized)
.must(() -> !this.isNull(item.getDefinition()))

View File

@ -66,11 +66,6 @@ public class PlanStatusDefinitionAuthorizationItemPersist {
@Override
protected List<Specification> specifications(PlanStatusDefinitionAuthorizationItemPersist item) {
return Arrays.asList(
this.spec()
.must(() -> !this.isListNullOrEmpty(item.getRoles()))
.failOn(PlanStatusDefinitionAuthorizationItemPersist._roles).failWith(messageSource.getMessage("Validation_Required", new Object[]{PlanStatusDefinitionAuthorizationItemPersist._roles}, LocaleContextHolder.getLocale())), this.spec()
.must(() -> !this.isListNullOrEmpty(item.getPlanRoles()))
.failOn(PlanStatusDefinitionAuthorizationItemPersist._planRoles).failWith(messageSource.getMessage("Validation_Required", new Object[]{PlanStatusDefinitionAuthorizationItemPersist._planRoles}, LocaleContextHolder.getLocale()))
);
}
}

View File

@ -2,6 +2,7 @@ package org.opencdmp.model.persist.planstatus;
import gr.cite.tools.validation.ValidatorFactory;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.enums.PlanStatusAvailableActionType;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
@ -19,11 +20,21 @@ public class PlanStatusDefinitionPersist {
public final static String _authorization = "authorization";
private PlanStatusDefinitionAuthorizationPersist authorization = null;
public final static String _availableActions = "availableActions";
private List<PlanStatusAvailableActionType> availableActions;
public PlanStatusDefinitionAuthorizationPersist getAuthorization() { return authorization; }
public void setAuthorization(PlanStatusDefinitionAuthorizationPersist authorization) { this.authorization = authorization; }
public List<PlanStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<PlanStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
@Component(PlanStatusDefinitionPersist.PlanStatusDefinitionPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class PlanStatusDefinitionPersistValidator extends BaseValidator<PlanStatusDefinitionPersist> {

View File

@ -26,6 +26,9 @@ public class PlanStatusPersist {
private String description;
public static final String _description = "description";
private String action;
public static final String _action = "action";
private org.opencdmp.commons.enums.PlanStatus internalStatus;
public static final String _internalStatus = "internalStatus";
@ -53,6 +56,14 @@ public class PlanStatusPersist {
public void setDescription(String description) { this.description = description; }
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public org.opencdmp.commons.enums.PlanStatus getInternalStatus() { return this.internalStatus; }
public void setInternalStatus(org.opencdmp.commons.enums.PlanStatus internalStatus) { this.internalStatus = internalStatus; }
@ -105,6 +116,10 @@ public class PlanStatusPersist {
.iff(() -> !this.isEmpty(item.getName()))
.must(() -> this.lessEqualLength(item.getName(), PlanStatusEntity._nameLength))
.failOn(org.opencdmp.model.persist.planstatus.PlanStatusPersist._name).failWith(this.messageSource.getMessage("Validation_MaxLength", new Object[]{org.opencdmp.model.persist.planstatus.PlanStatusPersist._name}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isEmpty(item.getAction()))
.must(() -> this.lessEqualLength(item.getAction(), PlanStatusEntity._actionLength))
.failOn(PlanStatusPersist._action).failWith(this.messageSource.getMessage("Validation_MaxLength", new Object[]{org.opencdmp.model.persist.planstatus.PlanStatusPersist._action}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> item.getInternalStatus() == org.opencdmp.commons.enums.PlanStatus.Finalized)
.must(() -> !this.isNull(item.getDefinition()))

View File

@ -1,13 +1,13 @@
package org.opencdmp.model.plan;
import org.opencdmp.commons.enums.PlanAccessType;
import org.opencdmp.commons.enums.PlanStatus;
import org.opencdmp.commons.enums.PlanVersionStatus;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.model.*;
import org.opencdmp.model.description.Description;
import org.opencdmp.model.planblueprint.PlanBlueprint;
import org.opencdmp.model.planreference.PlanReference;
import org.opencdmp.model.planstatus.PlanStatus;
import org.opencdmp.model.user.User;
import java.time.Instant;
@ -97,6 +97,11 @@ public class Plan {
private List<Plan> otherPlanVersions;
public static final String _otherPlanVersions = "otherPlanVersions";
private List<PlanStatus> availableStatuses;
public static final String _availableStatuses = "availableStatuses";
private List<String> statusAuthorizationFlags;
public static final String _statusAuthorizationFlags = "statusAuthorizationFlags";
private Boolean belongsToCurrentTenant;
public static final String _belongsToCurrentTenant = "belongsToCurrentTenant";
@ -318,4 +323,20 @@ public class Plan {
public void setOtherPlanVersions(List<Plan> otherPlanVersions) {
this.otherPlanVersions = otherPlanVersions;
}
public List<PlanStatus> getAvailableStatuses() {
return availableStatuses;
}
public void setAvailableStatuses(List<PlanStatus> availableStatuses) {
this.availableStatuses = availableStatuses;
}
public List<String> getStatusAuthorizationFlags() {
return statusAuthorizationFlags;
}
public void setStatusAuthorizationFlags(List<String> statusAuthorizationFlags) {
this.statusAuthorizationFlags = statusAuthorizationFlags;
}
}

View File

@ -16,6 +16,9 @@ public class PlanStatus {
public final static String _description = "description";
private String description;
public static final String _action = "action";
private String action;
public final static String _createdAt = "createdAt";
private Instant createdAt;
@ -61,6 +64,14 @@ public class PlanStatus {
public void setDescription(String description) { this.description = description; }
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public PlanStatusDefinition getDefinition() {
return this.definition;
}

View File

@ -1,12 +1,27 @@
package org.opencdmp.model.planstatus;
import org.opencdmp.commons.enums.PlanStatusAvailableActionType;
import java.util.List;
public class PlanStatusDefinition {
public final static String _authorization = "authorization";
private PlanStatusDefinitionAuthorization authorization;
public final static String _availableActions = "availableActions";
private List<PlanStatusAvailableActionType> availableActions;
public PlanStatusDefinitionAuthorization getAuthorization() { return this.authorization; }
public void setAuthorization(PlanStatusDefinitionAuthorization authorization) { this.authorization = authorization; }
public List<PlanStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<PlanStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
}

View File

@ -58,7 +58,7 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
private Collection<IsActive> isActives;
private Collection<DescriptionStatus> statuses;
private Collection<UUID> statusIds;
private Collection<UUID> planIds;
@ -72,6 +72,8 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
private Collection<UUID> planDescriptionTemplateIds;
private DescriptionStatusQuery descriptionStatusQuery;
private final TenantEntityManager tenantEntityManager;
public DescriptionQuery(UserScope userScope, AuthorizationService authService, QueryUtilsService queryUtilsService, TenantEntityManager tenantEntityManager) {
this.userScope = userScope;
@ -210,18 +212,18 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
return this;
}
public DescriptionQuery statuses(DescriptionStatus value) {
this.statuses = List.of(value);
public DescriptionQuery statusIds(UUID value) {
this.statusIds = List.of(value);
return this;
}
public DescriptionQuery statuses(DescriptionStatus... value) {
this.statuses = Arrays.asList(value);
public DescriptionQuery statusIds(UUID... value) {
this.statusIds = Arrays.asList(value);
return this;
}
public DescriptionQuery statuses(Collection<DescriptionStatus> values) {
this.statuses = values;
public DescriptionQuery statusIds(Collection<UUID> values) {
this.statusIds = values;
return this;
}
@ -250,6 +252,11 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
return this;
}
public DescriptionQuery descriptionStatusSubQuery(DescriptionStatusQuery subQuery) {
this.descriptionStatusQuery = subQuery;
return this;
}
@Override
protected EntityManager entityManager(){
return this.tenantEntityManager.getEntityManager();
@ -261,7 +268,7 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
this.isEmpty(this.ids) ||
this.isEmpty(this.isActives) || this.isEmpty(this.createdByIds) ||
this.isEmpty(this.excludedIds) || this.isFalseQuery(this.planQuery) ||
this.isEmpty(this.statuses) || this.isFalseQuery(this.planDescriptionTemplateQuery);
this.isEmpty(this.statusIds) || this.isFalseQuery(this.planDescriptionTemplateQuery);
}
@Override
@ -349,9 +356,9 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
inClause.value(item);
predicates.add(inClause);
}
if (this.statuses != null) {
CriteriaBuilder.In<DescriptionStatus> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._status));
for (DescriptionStatus item : this.statuses)
if (this.statusIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._statusId));
for (UUID item : this.statusIds)
inClause.value(item);
predicates.add(inClause);
}
@ -381,6 +388,10 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
inClause.value(item);
predicates.add(inClause);
}
if (this.descriptionStatusQuery != null) {
QueryContext<DescriptionStatusEntity, UUID> subQuery = this.applySubQuery(this.descriptionStatusQuery, queryContext, UUID.class, descriptionStatusEntityRoot -> descriptionStatusEntityRoot.get(DescriptionStatusEntity._id));
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DescriptionEntity._statusId)).value(subQuery.Query));
}
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
@ -399,7 +410,9 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
else if (item.prefix(Description._properties))
return DescriptionEntity._properties;
else if (item.match(Description._status) || item.match(PublicDescription._status))
return DescriptionEntity._status;
return DescriptionEntity._statusId;
else if (item.prefix(Description._status) || item.prefix(PublicDescription._status))
return DescriptionEntity._statusId;
else if (item.match(Description._description) || item.match(PublicDescription._description))
return DescriptionEntity._description;
else if (item.match(Description._createdBy))
@ -444,6 +457,7 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
item.setLabel(QueryBase.convertSafe(tuple, columns, DescriptionEntity._label, String.class));
item.setProperties(QueryBase.convertSafe(tuple, columns, DescriptionEntity._properties, String.class));
item.setStatus(QueryBase.convertSafe(tuple, columns, DescriptionEntity._status, DescriptionStatus.class));
item.setStatusId(QueryBase.convertSafe(tuple, columns, DescriptionEntity._statusId, UUID.class));
item.setDescription(QueryBase.convertSafe(tuple, columns, DescriptionEntity._description, String.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, DescriptionEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, DescriptionEntity._updatedAt, Instant.class));

View File

@ -188,6 +188,8 @@ public class DescriptionStatusQuery extends QueryBase<DescriptionStatusEntity> {
return DescriptionStatusEntity._name;
else if (item.match(DescriptionStatus._description))
return DescriptionStatusEntity._description;
else if (item.match(DescriptionStatus._action))
return DescriptionStatusEntity._action;
else if (item.match(DescriptionStatus._createdAt))
return DescriptionStatusEntity._createdAt;
else if (item.match(DescriptionStatus._updatedAt))
@ -200,6 +202,8 @@ public class DescriptionStatusQuery extends QueryBase<DescriptionStatusEntity> {
return DescriptionStatusEntity._internalStatus;
else if (item.match(DescriptionStatusEntity._definition))
return DescriptionStatusEntity._definition;
else if (item.prefix(DescriptionStatusEntity._definition))
return DescriptionStatusEntity._definition;
else
return null;
}
@ -210,6 +214,7 @@ public class DescriptionStatusQuery extends QueryBase<DescriptionStatusEntity> {
item.setId(QueryBase.convertSafe(tuple, columns, DescriptionStatusEntity._id, UUID.class));
item.setName(QueryBase.convertSafe(tuple, columns, DescriptionStatusEntity._name, String.class));
item.setDescription(QueryBase.convertSafe(tuple, columns, DescriptionStatusEntity._description, String.class));
item.setAction(QueryBase.convertSafe(tuple, columns, DescriptionStatusEntity._action, String.class));
item.setTenantId(QueryBase.convertSafe(tuple, columns, DescriptionStatusEntity._tenantId, UUID.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, DescriptionStatusEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, DescriptionStatusEntity._updatedAt, Instant.class));

View File

@ -39,7 +39,7 @@ public class PlanQuery extends QueryBase<PlanEntity> {
private Collection<IsActive> isActives;
private Collection<PlanStatus> statuses;
private Collection<UUID> statusIds;
private Collection<PlanVersionStatus> versionStatuses;
@ -61,6 +61,8 @@ public class PlanQuery extends QueryBase<PlanEntity> {
private EntityDoiQuery entityDoiQuery;
private PlanStatusQuery planStatusQuery;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
private final UserScope userScope;
@ -177,18 +179,18 @@ public class PlanQuery extends QueryBase<PlanEntity> {
return this;
}
public PlanQuery statuses(PlanStatus value) {
this.statuses = List.of(value);
public PlanQuery statusIds(UUID value) {
this.statusIds = List.of(value);
return this;
}
public PlanQuery statuses(PlanStatus... value) {
this.statuses = Arrays.asList(value);
public PlanQuery statusIds(UUID... value) {
this.statusIds = Arrays.asList(value);
return this;
}
public PlanQuery statuses(Collection<PlanStatus> values) {
this.statuses = values;
public PlanQuery statusIds(Collection<UUID> values) {
this.statusIds = values;
return this;
}
@ -253,6 +255,11 @@ public class PlanQuery extends QueryBase<PlanEntity> {
return this;
}
public PlanQuery planStatusSubQuery(PlanStatusQuery subQuery) {
this.planStatusQuery = subQuery;
return this;
}
public PlanQuery authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
@ -275,7 +282,7 @@ public class PlanQuery extends QueryBase<PlanEntity> {
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.creatorIds) || this.isEmpty(this.isActives) || this.isEmpty(this.versionStatuses) || this.isEmpty(this.excludedIds) || this.isEmpty(this.accessTypes) || this.isEmpty(this.statuses) || this.isFalseQuery(this.planDescriptionTemplateQuery) || this.isFalseQuery(this.planUserQuery);
return this.isEmpty(this.ids) || this.isEmpty(this.creatorIds) || this.isEmpty(this.isActives) || this.isEmpty(this.versionStatuses) || this.isEmpty(this.excludedIds) || this.isEmpty(this.accessTypes) || this.isEmpty(this.statusIds) || this.isFalseQuery(this.planDescriptionTemplateQuery) || this.isFalseQuery(this.planUserQuery);
}
@Override
@ -347,9 +354,9 @@ public class PlanQuery extends QueryBase<PlanEntity> {
inClause.value(item);
predicates.add(inClause);
}
if (this.statuses != null) {
CriteriaBuilder.In<PlanStatus> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(PlanEntity._status));
for (PlanStatus item : this.statuses)
if (this.statusIds != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(PlanEntity._statusId));
for (UUID item : this.statusIds)
inClause.value(item);
predicates.add(inClause);
}
@ -407,6 +414,11 @@ public class PlanQuery extends QueryBase<PlanEntity> {
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(PlanEntity._id)).value(subQuery.Query));
}
if (this.planStatusQuery != null) {
QueryContext<PlanStatusEntity, UUID> subQuery = this.applySubQuery(this.planStatusQuery, queryContext, UUID.class, planStatusEntityRoot -> planStatusEntityRoot.get(PlanStatusEntity._id));
predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(PlanEntity._statusId)).value(subQuery.Query));
}
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
@ -424,7 +436,9 @@ public class PlanQuery extends QueryBase<PlanEntity> {
else if (item.match(Plan._version) || item.match(PublicPlan._version))
return PlanEntity._version;
else if (item.match(Plan._status))
return PlanEntity._status;
return PlanEntity._statusId;
else if (item.prefix(Plan._status))
return PlanEntity._statusId;
else if (item.match(Plan._properties))
return PlanEntity._properties;
else if (item.prefix(Plan._properties))
@ -475,6 +489,7 @@ public class PlanQuery extends QueryBase<PlanEntity> {
item.setLabel(QueryBase.convertSafe(tuple, columns, PlanEntity._label, String.class));
item.setVersion(QueryBase.convertSafe(tuple, columns, PlanEntity._version, Short.class));
item.setStatus(QueryBase.convertSafe(tuple, columns, PlanEntity._status, PlanStatus.class));
item.setStatusId(QueryBase.convertSafe(tuple, columns, PlanEntity._statusId, UUID.class));
item.setVersionStatus(QueryBase.convertSafe(tuple, columns, PlanEntity._versionStatus, PlanVersionStatus.class));
item.setProperties(QueryBase.convertSafe(tuple, columns, PlanEntity._properties, String.class));
item.setGroupId(QueryBase.convertSafe(tuple, columns, PlanEntity._groupId, UUID.class));

View File

@ -36,6 +36,7 @@ public class PlanStatusQuery extends QueryBase<PlanStatusEntity> {
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
public PlanStatusQuery like(String value) {
this.like = value;
return this;
@ -187,8 +188,12 @@ public class PlanStatusQuery extends QueryBase<PlanStatusEntity> {
return PlanStatusEntity._description;
else if (item.match(PlanStatus._name))
return PlanStatusEntity._name;
else if (item.match(PlanStatus._action))
return PlanStatusEntity._action;
else if (item.match(PlanStatus._internalStatus))
return PlanStatusEntity._internalStatus;
else if (item.prefix(PlanStatus._definition))
return PlanStatusEntity._definition;
else if (item.match(PlanStatus._definition))
return PlanStatusEntity._definition;
else if (item.match(PlanStatus._createdAt))
@ -211,6 +216,7 @@ public class PlanStatusQuery extends QueryBase<PlanStatusEntity> {
item.setDescription(QueryBase.convertSafe(tuple, columns, PlanStatusEntity._description, String.class));
item.setDefinition(QueryBase.convertSafe(tuple, columns, PlanStatusEntity._definition, String.class));
item.setName(QueryBase.convertSafe(tuple, columns, PlanStatusEntity._name, String.class));
item.setAction(QueryBase.convertSafe(tuple, columns, PlanStatusEntity._action, String.class));
item.setInternalStatus(QueryBase.convertSafe(tuple, columns, PlanStatusEntity._internalStatus, org.opencdmp.commons.enums.PlanStatus.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, PlanStatusEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, PlanStatusEntity._updatedAt, Instant.class));

View File

@ -3,7 +3,6 @@ package org.opencdmp.query.lookup;
import gr.cite.tools.data.query.Lookup;
import gr.cite.tools.data.query.QueryFactory;
import org.apache.commons.lang3.StringUtils;
import org.opencdmp.commons.enums.DescriptionStatus;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.elastic.query.DescriptionElasticQuery;
import org.opencdmp.query.DescriptionQuery;
@ -31,7 +30,8 @@ public class DescriptionLookup extends Lookup {
private List<IsActive> isActive;
private List<DescriptionStatus> statuses;
private List<UUID> statusIds;
private DescriptionStatusLookup descriptionStatusSubQuery;
public String getLike() {
return this.like;
@ -65,12 +65,12 @@ public class DescriptionLookup extends Lookup {
this.isActive = isActive;
}
public List<DescriptionStatus> getStatuses() {
return this.statuses;
public List<UUID> getStatusIds() {
return statusIds;
}
public void setStatuses(List<DescriptionStatus> statuses) {
this.statuses = statuses;
public void setStatusIds(List<UUID> statusIds) {
this.statusIds = statusIds;
}
public PlanLookup getPlanSubQuery() {
@ -127,6 +127,14 @@ public class DescriptionLookup extends Lookup {
this.finalizedBefore = finalizedBefore;
}
public DescriptionStatusLookup getDescriptionStatusSubQuery() {
return descriptionStatusSubQuery;
}
public void setDescriptionStatusSubQuery(DescriptionStatusLookup descriptionStatusSubQuery) {
this.descriptionStatusSubQuery = descriptionStatusSubQuery;
}
public DescriptionQuery enrich(QueryFactory queryFactory) {
DescriptionQuery query = queryFactory.query(DescriptionQuery.class);
if (this.like != null) query.like(this.like);
@ -138,11 +146,12 @@ public class DescriptionLookup extends Lookup {
if (this.descriptionReferenceSubQuery != null) query.descriptionReferenceSubQuery(this.descriptionReferenceSubQuery.enrich(queryFactory));
if (this.descriptionTagSubQuery != null) query.descriptionTagSubQuery(this.descriptionTagSubQuery.enrich(queryFactory));
if (this.isActive != null) query.isActive(this.isActive);
if (this.statuses != null) query.statuses(this.statuses);
if (this.statusIds != null) query.statusIds(this.statusIds);
if (this.createdAfter != null) query.createdAfter(this.createdAfter);
if (this.createdBefore != null) query.createdBefore(this.createdBefore);
if (this.finalizedAfter != null) query.finalizedAfter(this.finalizedAfter);
if (this.finalizedBefore != null) query.finalizedBefore(this.finalizedBefore);
if (this.descriptionStatusSubQuery != null) query.descriptionStatusSubQuery(this.descriptionStatusSubQuery.enrich(queryFactory));
this.enrichCommon(query);
@ -154,7 +163,7 @@ public class DescriptionLookup extends Lookup {
if (this.like != null) query.like(StringUtils.strip(this.like, "%"));
if (this.ids != null) query.ids(this.ids);
if (this.excludedIds != null) query.excludedIds(this.excludedIds);
if (this.statuses != null) query.statuses(this.statuses);
if (this.statusIds != null) query.statusIds(this.statusIds);
if (this.createdAfter != null) query.createdAfter(this.createdAfter);
if (this.createdBefore != null) query.createdBefore(this.createdBefore);
if (this.finalizedAfter != null) query.finalizedAfter(this.finalizedAfter);

View File

@ -4,7 +4,6 @@ import gr.cite.tools.data.query.Lookup;
import gr.cite.tools.data.query.QueryFactory;
import org.apache.commons.lang3.StringUtils;
import org.opencdmp.commons.enums.PlanAccessType;
import org.opencdmp.commons.enums.PlanStatus;
import org.opencdmp.commons.enums.PlanVersionStatus;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.elastic.query.PlanElasticQuery;
@ -27,7 +26,7 @@ public class PlanLookup extends Lookup {
private List<IsActive> isActive;
private List<PlanVersionStatus> versionStatuses;
private List<PlanStatus> statuses;
private List<UUID> statusIds;
private List<PlanAccessType> accessTypes;
private List<Integer> versions;
@ -36,6 +35,7 @@ public class PlanLookup extends Lookup {
private PlanUserLookup planUserSubQuery;
private PlanBlueprintLookup planBlueprintSubQuery;
private PlanReferenceLookup planReferenceSubQuery;
private PlanStatusLookup planStatusSubQuery;
public String getLike() {
return this.like;
@ -73,12 +73,12 @@ public class PlanLookup extends Lookup {
this.isActive = isActive;
}
public List<PlanStatus> getStatuses() {
return this.statuses;
public List<UUID> getStatusIds() {
return statusIds;
}
public void setStatuses(List<PlanStatus> statuses) {
this.statuses = statuses;
public void setStatusIds(List<UUID> statusIds) {
this.statusIds = statusIds;
}
public List<Integer> getVersions() {
@ -138,6 +138,14 @@ public class PlanLookup extends Lookup {
public void setPlanReferenceLookup(PlanReferenceLookup planReferenceSubQuery) { this.planReferenceSubQuery = planReferenceSubQuery; }
public PlanStatusLookup getPlanStatusSubQuery() {
return planStatusSubQuery;
}
public void setPlanStatusSubQuery(PlanStatusLookup planStatusSubQuery) {
this.planStatusSubQuery = planStatusSubQuery;
}
public PlanQuery enrich(QueryFactory queryFactory) {
PlanQuery query = queryFactory.query(PlanQuery.class);
if (this.like != null) query.like(this.like);
@ -147,13 +155,14 @@ public class PlanLookup extends Lookup {
if (this.excludedIds != null) query.excludedIds(this.excludedIds);
if (this.accessTypes != null) query.accessTypes(this.accessTypes);
if (this.isActive != null) query.isActive(this.isActive);
if (this.statuses != null) query.statuses(this.statuses);
if (this.statusIds != null) query.statusIds(this.statusIds);
if (this.versions != null) query.versions(this.versions);
if (this.versionStatuses != null) query.versionStatuses(this.versionStatuses);
if (this.planDescriptionTemplateSubQuery != null) query.planDescriptionTemplateSubQuery(this.planDescriptionTemplateSubQuery.enrich(queryFactory));
if (this.planUserSubQuery != null) query.planUserSubQuery(this.planUserSubQuery.enrich(queryFactory));
if (this.planBlueprintSubQuery != null) query.planBlueprintSubQuery(this.planBlueprintSubQuery.enrich(queryFactory));
if (this.planReferenceSubQuery != null) query.planReferenceSubQuery(this.planReferenceSubQuery.enrich(queryFactory));
if (this.planStatusSubQuery != null) query.planStatusSubQuery(this.planStatusSubQuery.enrich(queryFactory));
this.enrichCommon(query);
@ -167,7 +176,7 @@ public class PlanLookup extends Lookup {
if (this.groupIds != null) query.groupIds(this.groupIds);
if (this.excludedIds != null) query.excludedIds(this.excludedIds);
if (this.accessTypes != null) query.accessTypes(this.accessTypes);
if (this.statuses != null) query.statuses(this.statuses);
if (this.statusIds != null) query.statuses(this.statusIds);
if (this.versions != null) query.versions(this.versions);
if (this.versionStatuses != null) query.versionStatuses(this.versionStatuses);
if (this.planDescriptionTemplateSubQuery != null) query.planDescriptionTemplateSubQuery(this.planDescriptionTemplateSubQuery.enrichElasticInner(queryFactory));
@ -175,6 +184,7 @@ public class PlanLookup extends Lookup {
if (this.planBlueprintSubQuery != null && this.planBlueprintSubQuery.getIds() != null && !this.planBlueprintSubQuery.getIds().isEmpty()) query.blueprintIds(this.planBlueprintSubQuery.getIds());
if (this.planReferenceSubQuery != null) query.referenceSubQuery(this.planReferenceSubQuery.enrichElasticInner(queryFactory));
if (this.tenantSubQuery != null) throw new UnsupportedOperationException();
if (this.planStatusSubQuery != null) throw new UnsupportedOperationException();
this.enrichCommon(query);
@ -188,7 +198,7 @@ public class PlanLookup extends Lookup {
if (this.groupIds != null) query.groupIds(this.groupIds);
if (this.excludedIds != null) query.excludedIds(this.excludedIds);
if (this.accessTypes != null) query.accessTypes(this.accessTypes);
if (this.statuses != null) query.statuses(this.statuses);
if (this.statusIds != null) query.statusIds(this.statusIds);
if (this.versions != null) query.versions(this.versions);
if (this.versionStatuses != null) query.versionStatuses(this.versionStatuses);
if (this.planDescriptionTemplateSubQuery != null) throw new UnsupportedOperationException("");
@ -196,6 +206,7 @@ public class PlanLookup extends Lookup {
if (this.planBlueprintSubQuery != null && this.planBlueprintSubQuery.getIds() != null && !this.planBlueprintSubQuery.getIds().isEmpty()) throw new UnsupportedOperationException("");
if (this.planReferenceSubQuery != null) throw new UnsupportedOperationException("");
if (this.tenantSubQuery != null) throw new UnsupportedOperationException();
if (this.planStatusSubQuery != null) throw new UnsupportedOperationException();
return query;
}

View File

@ -108,8 +108,7 @@ public class QueryUtilsServiceImpl implements QueryUtilsService {
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(PlanUserEntity._planId))
.filterFunc((subQueryRoot, cb) ->
userId != null ? cb.and(
cb.equal(subQueryRoot.get(PlanUserEntity._userId), userId),
cb.equal(subQueryRoot.get(PlanUserEntity._isActive), IsActive.Active)
cb.equal(subQueryRoot.get(PlanUserEntity._userId), userId)
) : cb.or() //Creates a false query
)
));

View File

@ -0,0 +1,11 @@
package org.opencdmp.service.custompolicy;
import gr.cite.tools.cache.CacheOptions;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "cache.custom-policy-by-tenant")
public class CustomPolicyCacheOptions extends CacheOptions {
}

View File

@ -0,0 +1,86 @@
package org.opencdmp.service.custompolicy;
import gr.cite.tools.cache.CacheService;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
import org.opencdmp.event.DescriptionStatusTouchedEvent;
import org.opencdmp.event.PlanStatusTouchedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@Service
public class CustomPolicyCacheService extends CacheService<CustomPolicyCacheService.CustomPolicyCacheValue> {
public static class CustomPolicyCacheValue {
public CustomPolicyCacheValue() {}
public CustomPolicyCacheValue(String tenantCode, Map<UUID, PlanStatusDefinitionEntity> planStatusDefinitionMap, Map<UUID, DescriptionStatusDefinitionEntity> descriptionStatusDefinitionMap) {
this.tenantCode = tenantCode;
this.planStatusDefinitionMap = planStatusDefinitionMap;
this.descriptionStatusDefinitionMap = descriptionStatusDefinitionMap;
}
private String tenantCode;
private Map<UUID, PlanStatusDefinitionEntity> planStatusDefinitionMap;
private Map<UUID, DescriptionStatusDefinitionEntity> descriptionStatusDefinitionMap;
public String getTenantCode() {
return tenantCode;
}
public void setTenantCode(String tenantCode) {
this.tenantCode = tenantCode;
}
public Map<UUID, PlanStatusDefinitionEntity> getPlanStatusDefinitionMap() {
return planStatusDefinitionMap;
}
public void setPlanStatusDefinitionMap(Map<UUID, PlanStatusDefinitionEntity> planStatusDefinitionMap) {
this.planStatusDefinitionMap = planStatusDefinitionMap;
}
public Map<UUID, DescriptionStatusDefinitionEntity> getDescriptionStatusDefinitionMap() {
return descriptionStatusDefinitionMap;
}
public void setDescriptionStatusDefinitionMap(Map<UUID, DescriptionStatusDefinitionEntity> descriptionStatusDefinitionMap) {
this.descriptionStatusDefinitionMap = descriptionStatusDefinitionMap;
}
}
public void clearCache(PlanStatusTouchedEvent event) {
this.evict(this.buildKey(event.getTenantCode()));
}
public void clearCache(DescriptionStatusTouchedEvent event) {
this.evict(this.buildKey(event.getTenantCode()));
}
@Autowired
public CustomPolicyCacheService(CustomPolicyCacheOptions options) {
super(options);
}
@Override
protected Class<CustomPolicyCacheValue> valueClass() {return CustomPolicyCacheValue.class;}
public String keyOf(CustomPolicyCacheValue value) {
return this.buildKey(value.getTenantCode());
}
public String buildKey(String tenantCode) {
HashMap<String, String> keyParts = new HashMap<>();
keyParts.put("$tenantCode$", tenantCode);
return this.generateKey(keyParts);
}
}

View File

@ -0,0 +1,26 @@
package org.opencdmp.service.custompolicy;
import gr.cite.commons.web.authz.configuration.Permission;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public interface CustomPolicyService {
HashMap<String, Permission> buildPlanStatusPolicies();
Map<UUID, PlanStatusDefinitionEntity> buildPlanStatusDefinitionMap();
Map<UUID, DescriptionStatusDefinitionEntity> buildDescriptionStatusDefinitionMap();
String getPlanStatusCanEditStatusPermission(UUID id);
HashMap<String, Permission> buildDescriptionStatusPolicies();
String getDescriptionStatusCanEditStatusPermission(UUID id);
}

View File

@ -0,0 +1,136 @@
package org.opencdmp.service.custompolicy;
import gr.cite.commons.web.authz.configuration.Permission;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
import org.opencdmp.data.DescriptionStatusEntity;
import org.opencdmp.data.PlanStatusEntity;
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
import org.opencdmp.model.descriptionstatus.DescriptionStatusDefinitionAuthorization;
import org.opencdmp.model.planstatus.PlanStatus;
import org.opencdmp.model.planstatus.PlanStatusDefinitionAuthorization;
import org.opencdmp.query.DescriptionStatusQuery;
import org.opencdmp.query.PlanStatusQuery;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
import java.util.*;
@Service
public class CustomPolicyServiceImpl implements CustomPolicyService{
private final QueryFactory queryFactory;
private final XmlHandlingService xmlHandlingService;
private final TenantScope tenantScope;
private final CustomPolicyCacheService customPolicyCacheService;
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(CustomPolicyServiceImpl.class));
public CustomPolicyServiceImpl(QueryFactory queryFactory, XmlHandlingService xmlHandlingService, TenantScope tenantScope, CustomPolicyCacheService customPolicyCacheService) {
this.queryFactory = queryFactory;
this.xmlHandlingService = xmlHandlingService;
this.tenantScope = tenantScope;
this.customPolicyCacheService = customPolicyCacheService;
}
@Override
public HashMap<String, Permission> buildPlanStatusPolicies() {
HashMap<String, Permission> policies = new HashMap<>();
Map<UUID, PlanStatusDefinitionEntity> map = this.buildPlanStatusDefinitionMap();
if (map == null) return policies;
for (UUID statusId: map.keySet()) {
PlanStatusDefinitionEntity definition = map.get(statusId);
if (definition != null && definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null) {
policies.put(this.getPlanStatusCanEditStatusPermission(statusId), new Permission(new HashSet<>(definition.getAuthorization().getEdit().getRoles()), new ArrayList<>(), new HashSet<>(), definition.getAuthorization().getEdit().getAllowAnonymous(), definition.getAuthorization().getEdit().getAllowAuthenticated()));
}
}
return policies;
}
@Override
public HashMap<String, Permission> buildDescriptionStatusPolicies(){
HashMap<String, Permission> policies = new HashMap<>();
Map<UUID, DescriptionStatusDefinitionEntity> map = this.buildDescriptionStatusDefinitionMap();
if (map == null) return policies;
for (UUID statusId: map.keySet()) {
DescriptionStatusDefinitionEntity definition = map.get(statusId);
if (definition != null && definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null) {
policies.put(this.getDescriptionStatusCanEditStatusPermission(statusId), new Permission(new HashSet<>(definition.getAuthorization().getEdit().getRoles()), new ArrayList<>(), new HashSet<>(), definition.getAuthorization().getEdit().getAllowAnonymous(), definition.getAuthorization().getEdit().getAllowAuthenticated()));
}
}
return policies;
}
@Override
public Map<UUID, PlanStatusDefinitionEntity> buildPlanStatusDefinitionMap() {
HashMap<String, Permission> policies = new HashMap<>();
String tenantCode = null;
try {
tenantCode = this.tenantScope.isSet() && this.tenantScope.isMultitenant() ? this.tenantScope.getTenantCode() : this.tenantScope.getDefaultTenantCode();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
CustomPolicyCacheService.CustomPolicyCacheValue cacheValue = this.customPolicyCacheService.lookup(this.customPolicyCacheService.buildKey(tenantCode));
if (cacheValue == null || cacheValue.getPlanStatusDefinitionMap() == null) {
Map<UUID, PlanStatusDefinitionEntity> definitionStatusMap = new HashMap<>();
List<PlanStatusEntity> entities = this.queryFactory.query(PlanStatusQuery.class).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(PlanStatus._id).ensure(PlanStatus._definition));
for (PlanStatusEntity entity: entities) {
PlanStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(PlanStatusDefinitionEntity.class, entity.getDefinition());
if (definition != null) {
definitionStatusMap.put(entity.getId(), definition);
}
}
cacheValue = new CustomPolicyCacheService.CustomPolicyCacheValue(tenantCode, definitionStatusMap, cacheValue != null ? cacheValue.getDescriptionStatusDefinitionMap() : null);
this.customPolicyCacheService.put(cacheValue);
}
return cacheValue.getPlanStatusDefinitionMap();
}
@Override
public Map<UUID, DescriptionStatusDefinitionEntity> buildDescriptionStatusDefinitionMap(){
HashMap<String, Permission> policies = new HashMap<>();
String tenantCode = null;
try {
tenantCode = this.tenantScope.isSet() && this.tenantScope.isMultitenant() ? this.tenantScope.getTenantCode() : this.tenantScope.getDefaultTenantCode();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
CustomPolicyCacheService.CustomPolicyCacheValue cacheValue = this.customPolicyCacheService.lookup(this.customPolicyCacheService.buildKey(tenantCode));
if (cacheValue == null || cacheValue.getDescriptionStatusDefinitionMap() == null) {
Map<UUID, DescriptionStatusDefinitionEntity> definitionStatusMap = new HashMap<>();
List<DescriptionStatusEntity> entities = this.queryFactory.query(DescriptionStatusQuery.class).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(DescriptionStatus._id).ensure(DescriptionStatus._definition));
for (DescriptionStatusEntity entity : entities) {
DescriptionStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(DescriptionStatusDefinitionEntity.class, entity.getDefinition());
if (definition != null) {
definitionStatusMap.put(entity.getId(), definition);
}
}
cacheValue = new CustomPolicyCacheService.CustomPolicyCacheValue(tenantCode, cacheValue != null ? cacheValue.getPlanStatusDefinitionMap(): null, definitionStatusMap);
this.customPolicyCacheService.put(cacheValue);
}
return cacheValue.getDescriptionStatusDefinitionMap();
}
@Override
public String getPlanStatusCanEditStatusPermission(UUID id){
return ("PlanStatus" + "_" + id + "_" + PlanStatusDefinitionAuthorization._edit).toLowerCase();
}
@Override
public String getDescriptionStatusCanEditStatusPermission(UUID id){
return ("DescriptionStatus" + "_" + id + "_" + DescriptionStatusDefinitionAuthorization._edit).toLowerCase();
}
}

View File

@ -77,9 +77,9 @@ public class DashboardServiceImpl implements DashboardService {
descriptionLookup.getPage().setOffset(0);
descriptionLookup.getPage().setSize(model.getPage().getSize()+model.getPage().getOffset());
QueryResult<Description> descriptions = this.elasticQueryHelperService.collect(descriptionLookup, AuthorizationFlags.AllExceptPublic, new BaseFieldSet().ensure(Description._id).ensure(Description._updatedAt).ensure(Description._status).ensure(Description._label));
QueryResult<Description> descriptions = this.elasticQueryHelperService.collect(descriptionLookup, AuthorizationFlags.AllExceptPublic, new BaseFieldSet().ensure(Description._id).ensure(Description._updatedAt).ensure(String.join(".",Description._status, org.opencdmp.model.descriptionstatus.DescriptionStatus._id)).ensure(Description._label));
if (!this.conventionService.isListNullOrEmpty(descriptions.getItems())) {
for (Description description : descriptions.getItems()) recentActivityItemEntities.add(new RecentActivityItemEntity(RecentActivityItemType.Description, description.getId(), description.getUpdatedAt(), description.getLabel(), description.getStatus().getValue()));
for (Description description : descriptions.getItems()) recentActivityItemEntities.add(new RecentActivityItemEntity(RecentActivityItemType.Description, description.getId(), description.getUpdatedAt(), description.getLabel(), description.getStatus().getId()));
}
}
@ -88,9 +88,9 @@ public class DashboardServiceImpl implements DashboardService {
planLookup.getPage().setOffset(0);
planLookup.getPage().setSize(model.getPage().getSize()+model.getPage().getOffset());
QueryResult<Plan> plans = this.elasticQueryHelperService.collect(planLookup, AuthorizationFlags.AllExceptPublic, new BaseFieldSet().ensure(Plan._id).ensure(Plan._updatedAt).ensure(Plan._label).ensure(Plan._status));
QueryResult<Plan> plans = this.elasticQueryHelperService.collect(planLookup, AuthorizationFlags.AllExceptPublic, new BaseFieldSet().ensure(Plan._id).ensure(Plan._updatedAt).ensure(Plan._label).ensure(String.join(".",Plan._status, org.opencdmp.model.planstatus.PlanStatus._id)));
if (!this.conventionService.isListNullOrEmpty(plans.getItems())) {
for (Plan plan : plans.getItems()) recentActivityItemEntities.add(new RecentActivityItemEntity(RecentActivityItemType.Plan, plan.getId(), plan.getUpdatedAt(), plan.getLabel(), plan.getStatus().getValue()));
for (Plan plan : plans.getItems()) recentActivityItemEntities.add(new RecentActivityItemEntity(RecentActivityItemType.Plan, plan.getId(), plan.getUpdatedAt(), plan.getLabel(), plan.getStatus().getId()));
}
}
@ -100,7 +100,7 @@ public class DashboardServiceImpl implements DashboardService {
switch (model.getOrderField()){
case Label -> comparator = Comparator.comparing(RecentActivityItemEntity::getLabel).thenComparing(RecentActivityItemEntity::getUpdatedAt);
case UpdatedAt -> comparator = Comparator.comparing(RecentActivityItemEntity::getUpdatedAt);
case Status -> comparator = Comparator.comparing(RecentActivityItemEntity::getStatusValue).thenComparing(RecentActivityItemEntity::getUpdatedAt);
case Status -> comparator = Comparator.comparing(RecentActivityItemEntity::getStatusId).thenComparing(RecentActivityItemEntity::getUpdatedAt);
default -> throw new IllegalArgumentException("Type not found" + model.getOrderField()) ;
}
}
@ -118,10 +118,12 @@ public class DashboardServiceImpl implements DashboardService {
DashboardStatisticsCacheService.DashboardStatisticsCacheValue cacheValue = this.dashboardStatisticsCacheService.lookup(this.dashboardStatisticsCacheService.buildKey(DashboardStatisticsCacheService.publicKey));
if (cacheValue == null || cacheValue.getDashboardStatistics() == null) {
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().isActive(IsActive.Active).versionStatuses(PlanVersionStatus.Current).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public);
PlanStatusQuery planStatusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().isActive(IsActive.Active).versionStatuses(PlanVersionStatus.Current).planStatusSubQuery(planStatusQuery).accessTypes(PlanAccessType.Public);
DashboardStatistics statistics = new DashboardStatistics();
statistics.setPlanCount(planQuery.authorize(EnumSet.of(Public)).count());
statistics.setDescriptionCount(this.queryFactory.query(DescriptionQuery.class).disableTracking().isActive(IsActive.Active).planSubQuery(planQuery).statuses(DescriptionStatus.Finalized).authorize(EnumSet.of(Public)).count());
DescriptionStatusQuery descriptionStatusQuery = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active);
statistics.setDescriptionCount(this.queryFactory.query(DescriptionQuery.class).disableTracking().isActive(IsActive.Active).planSubQuery(planQuery).descriptionStatusSubQuery(descriptionStatusQuery).authorize(EnumSet.of(Public)).count());
statistics.setReferenceTypeStatistics(new ArrayList<>());
if (!this.conventionService.isListNullOrEmpty(this.config.getReferenceTypeCounters())){

View File

@ -24,6 +24,7 @@ import org.opencdmp.commonmodels.models.reference.ReferenceModel;
import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.*;
import org.opencdmp.commons.enums.DescriptionStatus;
import org.opencdmp.commons.notification.NotificationProperties;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.scope.user.UserScope;
@ -68,7 +69,9 @@ import org.opencdmp.model.reference.Reference;
import org.opencdmp.model.referencetype.ReferenceType;
import org.opencdmp.query.*;
import org.opencdmp.service.accounting.AccountingService;
import org.opencdmp.service.custompolicy.CustomPolicyService;
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
import org.opencdmp.service.elastic.ElasticService;
import org.opencdmp.service.filetransformer.FileTransformerService;
import org.opencdmp.service.responseutils.ResponseUtilsService;
@ -141,6 +144,8 @@ public class DescriptionServiceImpl implements DescriptionService {
private final TagService tagService;
private final UsageLimitService usageLimitService;
private final AccountingService accountingService;
private final DescriptionWorkflowService descriptionWorkflowService;
private final CustomPolicyService customPolicyService;
@Autowired
public DescriptionServiceImpl(
@ -155,7 +160,7 @@ public class DescriptionServiceImpl implements DescriptionService {
QueryFactory queryFactory,
JsonHandlingService jsonHandlingService,
UserScope userScope,
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService, UsageLimitService usageLimitService, AccountingService accountingService) {
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService, CustomPolicyService customPolicyService) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -184,6 +189,8 @@ public class DescriptionServiceImpl implements DescriptionService {
this.tagService = tagService;
this.usageLimitService = usageLimitService;
this.accountingService = accountingService;
this.descriptionWorkflowService = descriptionWorkflowService;
this.customPolicyService = customPolicyService;
}
@Override
@ -223,9 +230,17 @@ public class DescriptionServiceImpl implements DescriptionService {
data = this.entityManager.find(DescriptionEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
if (data.getStatus().equals(DescriptionStatus.Finalized)) throw new MyValidationException(this.errors.getDescriptionIsFinalized().getCode(), this.errors.getDescriptionIsFinalized().getMessage());
DescriptionStatusEntity oldDescriptionStatusEntity = this.entityManager.find(DescriptionStatusEntity.class, data.getStatusId(), true);
if (oldDescriptionStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getStatusId(), org.opencdmp.model.descriptionstatus.DescriptionStatus.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (oldDescriptionStatusEntity.getInternalStatus() != null && oldDescriptionStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) throw new MyValidationException(this.errors.getDescriptionIsFinalized().getCode(), this.errors.getDescriptionIsFinalized().getMessage());
if (!data.getPlanId().equals(model.getPlanId())) throw new MyValidationException(this.errors.getPlanCanNotChange().getCode(), this.errors.getPlanCanNotChange().getMessage());
if (!data.getPlanDescriptionTemplateId().equals(model.getPlanDescriptionTemplateId())) throw new MyValidationException(this.errors.getPlanDescriptionTemplateCanNotChange().getCode(), this.errors.getPlanDescriptionTemplateCanNotChange().getMessage());
if (model.getStatusId() != null && !model.getStatusId().equals(data.getStatusId())) {
data.setStatusId(model.getStatusId());
DescriptionStatusEntity newDescriptionStatusEntity = this.entityManager.find(DescriptionStatusEntity.class, model.getStatusId(), true);
if (newDescriptionStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getStatusId(), org.opencdmp.model.descriptionstatus.DescriptionStatus.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (newDescriptionStatusEntity.getInternalStatus() != null && newDescriptionStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) data.setFinalizedAt(Instant.now());
}
} else {
this.usageLimitService.checkIncrease(UsageLimitTargetMetric.DESCRIPTION_COUNT);
@ -244,6 +259,8 @@ public class DescriptionServiceImpl implements DescriptionService {
data.setCreatedById(this.userScope.getUserId());
data.setPlanId(model.getPlanId());
data.setPlanDescriptionTemplateId(model.getPlanDescriptionTemplateId());
data.setStatus(DescriptionStatus.Draft);
data.setStatusId(this.descriptionWorkflowService.getWorkFlowDefinition().getStartingStatusId());
}
DescriptionTemplateEntity descriptionTemplateEntity = this.entityManager.find(DescriptionTemplateEntity.class, model.getDescriptionTemplateId(), true);
@ -253,12 +270,12 @@ public class DescriptionServiceImpl implements DescriptionService {
PlanEntity plan = this.entityManager.find(PlanEntity.class, data.getPlanId(), true);
if (plan == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getPlanId(), Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
PlanStatusEntity planStatusEntity = this.entityManager.find(PlanStatusEntity.class, plan.getStatusId(), true);
if (planStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{plan.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (plan.getStatus().equals(PlanStatus.Finalized)) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
if (planStatusEntity.getInternalStatus() != null && planStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
data.setLabel(model.getLabel());
data.setStatus(model.getStatus());
if (model.getStatus() == DescriptionStatus.Finalized) data.setFinalizedAt(Instant.now());
data.setDescription(model.getDescription());
data.setDescriptionTemplateId(model.getDescriptionTemplateId());
data.setUpdatedAt(Instant.now());
@ -376,6 +393,10 @@ public class DescriptionServiceImpl implements DescriptionService {
}
private void sendNotification(DescriptionEntity description, Boolean isUpdate) throws InvalidApplicationException {
DescriptionStatusEntity descriptionStatusEntity = this.entityManager.find(DescriptionStatusEntity.class, description.getStatusId(), true);
if (descriptionStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{description, DescriptionStatus.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (descriptionStatusEntity.getInternalStatus() != null && descriptionStatusEntity.getInternalStatus().equals(DescriptionStatus.Canceled)) return;
List<PlanUserEntity> existingUsers = this.queryFactory.query(PlanUserQuery.class).disableTracking()
.planIds(description.getPlanId())
.isActives(IsActive.Active)
@ -388,7 +409,7 @@ public class DescriptionServiceImpl implements DescriptionService {
if (!planUser.getUserId().equals(this.userScope.getUserIdSafe())){
UserEntity user = this.queryFactory.query(UserQuery.class).disableTracking().ids(planUser.getUserId()).first();
if (user == null || user.getIsActive().equals(IsActive.Inactive)) throw new MyValidationException(this.errors.getPlanInactiveUser().getCode(), this.errors.getPlanInactiveUser().getMessage());
this.createDescriptionNotificationEvent(description, user, isUpdate);
this.createDescriptionNotificationEvent(description, descriptionStatusEntity, user, isUpdate);
}
}
}
@ -437,17 +458,19 @@ public class DescriptionServiceImpl implements DescriptionService {
return cleanData;
}
private void createDescriptionNotificationEvent(DescriptionEntity description, UserEntity user, Boolean isUpdate) throws InvalidApplicationException {
private void createDescriptionNotificationEvent(DescriptionEntity description, DescriptionStatusEntity descriptionStatus, UserEntity user, Boolean isUpdate) throws InvalidApplicationException {
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
event.setUserId(user.getId());
this.applyNotificationType(description.getStatus(), event, isUpdate);
if (descriptionStatus.getInternalStatus() == null) event.setNotificationType(this.notificationProperties.getDescriptionStatusChangedType());
else this.applyNotificationType(descriptionStatus.getInternalStatus(), event, isUpdate);
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));
fieldInfoList.add(new FieldInfo("{reasonName}", DataType.String, this.queryFactory.query(UserQuery.class).disableTracking().ids(this.userScope.getUserId()).first().getName()));
fieldInfoList.add(new FieldInfo("{name}", DataType.String, description.getLabel()));
fieldInfoList.add(new FieldInfo("{id}", DataType.String, description.getId().toString()));
if (descriptionStatus.getInternalStatus() == null) fieldInfoList.add(new FieldInfo("{statusName}", DataType.String, descriptionStatus.getName()));
if(this.tenantScope.getTenantCode() != null && !this.tenantScope.getTenantCode().equals(this.tenantScope.getDefaultTenantCode())){
fieldInfoList.add(new FieldInfo("{tenant-url-path}", DataType.String, String.format("/t/%s", this.tenantScope.getTenantCode())));
}
@ -479,19 +502,32 @@ public class DescriptionServiceImpl implements DescriptionService {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.EditDescription);
DescriptionEntity data = this.entityManager.find(DescriptionEntity.class, model.getId());
DescriptionEntity data = this.queryFactory.query(DescriptionQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(model.getId()).isActive(IsActive.Active).first();
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
try {
this.authorizationService.authorizeForce(this.customPolicyService.getDescriptionStatusCanEditStatusPermission(model.getStatusId()));
} catch (Exception e) {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(data.getPlanId())), this.customPolicyService.getDescriptionStatusCanEditStatusPermission(model.getStatusId()));
}
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
if (!data.getStatus().equals(model.getStatus())){
if (data.getStatus().equals(DescriptionStatus.Finalized)){
if (!data.getStatusId().equals(model.getStatusId())){
DescriptionStatusEntity oldStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().ids(data.getStatusId()).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id).ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._internalStatus));
if (oldStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getStatusId(), DescriptionStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (oldStatusEntity.getInternalStatus() != null && oldStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)){
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.FinalizeDescription);
PlanEntity planEntity = this.entityManager.find(PlanEntity.class, data.getPlanId(), true);
if (planEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getPlanId(), PlanEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if(!planEntity.getStatus().equals(PlanStatus.Draft)) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
PlanStatusEntity planStatusEntity = this.entityManager.find(PlanStatusEntity.class, planEntity.getStatusId(), true);
if (planStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{planEntity.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (planStatusEntity.getInternalStatus() != null && planStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
}
data.setStatus(model.getStatus());
if (model.getStatus() == DescriptionStatus.Finalized) data.setFinalizedAt(Instant.now());
data.setStatusId(model.getStatusId());
DescriptionStatusEntity newStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().ids(model.getStatusId()).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id).ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._internalStatus));
if (newStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getStatusId(), DescriptionStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (newStatusEntity.getInternalStatus() != null && newStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) data.setFinalizedAt(Instant.now());
data.setUpdatedAt(Instant.now());
this.entityManager.merge(data);
@ -501,7 +537,7 @@ public class DescriptionServiceImpl implements DescriptionService {
this.eventBroker.emit(new DescriptionTouchedEvent(data.getId()));
this.annotationEntityTouchedIntegrationEventHandler.handleDescription(data.getId());
if (data.getStatus().equals(DescriptionStatus.Finalized)) this.sendNotification(data, true);
this.sendNotification(data, true);
}
return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(BaseFieldSet.build(fields, Description._id), data);
}
@ -514,11 +550,14 @@ public class DescriptionServiceImpl implements DescriptionService {
return null;
}
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
if (statusEntity == null) throw new MyApplicationException("finalized status not found");
for (DescriptionEntity description: descriptions) {
DescriptionValidationResult descriptionValidationResult = new DescriptionValidationResult(description.getId(), DescriptionValidationOutput.Invalid);
DescriptionPersist.DescriptionPersistValidator validator = this.validatorFactory.validator(DescriptionPersist.DescriptionPersistValidator.class);
validator.validate(this.buildDescriptionPersist(description));
validator.validate(this.buildDescriptionPersist(description, statusEntity.getId()));
if (validator.result().isValid()) descriptionValidationResult.setResult(DescriptionValidationOutput.Valid);
descriptionValidationResults.add(descriptionValidationResult);
@ -994,7 +1033,7 @@ public class DescriptionServiceImpl implements DescriptionService {
//region build persist
private @NotNull DescriptionPersist buildDescriptionPersist(DescriptionEntity data) throws InvalidApplicationException {
private @NotNull DescriptionPersist buildDescriptionPersist(DescriptionEntity data, UUID statusId) throws InvalidApplicationException {
DescriptionPersist persist = new DescriptionPersist();
if (data == null) return persist;
@ -1003,7 +1042,7 @@ public class DescriptionServiceImpl implements DescriptionService {
persist.setId(data.getId());
persist.setLabel(data.getLabel());
persist.setStatus(DescriptionStatus.Finalized);
persist.setStatusId(statusId);
persist.setDescription(data.getDescription());
persist.setDescriptionTemplateId(data.getDescriptionTemplateId());
persist.setPlanId(data.getPlanId());
@ -1174,7 +1213,8 @@ public class DescriptionServiceImpl implements DescriptionService {
} else {
try {
this.entityManager.disableTenantFilters();
data = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public)).first();
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
data = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public)).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();
@ -1207,7 +1247,8 @@ public class DescriptionServiceImpl implements DescriptionService {
DescriptionEntity data = null;
try {
this.entityManager.disableTenantFilters();
data = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public)).first();
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
data = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public)).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();
@ -1225,6 +1266,7 @@ public class DescriptionServiceImpl implements DescriptionService {
xml.setId(data.getId());
xml.setDescription(data.getDescription());
xml.setLabel(data.getLabel());
xml.setStatus(this.descriptionStatusImportExportToExport(data.getStatusId()));
xml.setFinalizedAt(data.getFinalizedAt());
PlanDescriptionTemplateEntity planDescriptionTemplateEntity = this.queryFactory.query(PlanDescriptionTemplateQuery.class).disableTracking().ids(data.getPlanDescriptionTemplateId()).authorize(AuthorizationFlags.All).isActive(IsActive.Active).first();
@ -1261,6 +1303,17 @@ public class DescriptionServiceImpl implements DescriptionService {
return xml;
}
private DescriptionStatusImportExport descriptionStatusImportExportToExport(UUID statusId) throws InvalidApplicationException {
DescriptionStatusImportExport xml = new DescriptionStatusImportExport();
if (statusId == null) return xml;
DescriptionStatusEntity statusEntity = this.entityManager.find(DescriptionStatusEntity.class, statusId, true);
if (statusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{statusId, DescriptionStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
xml.setId(statusEntity.getId());
xml.setName(statusEntity.getName());
return xml;
}
private DescriptionReferenceImportExport descriptionReferenceToExport(DescriptionReferenceEntity entity, Map<UUID, ReferenceEntity> referenceEntityMap, Map<UUID, ReferenceTypeEntity> referenceTypeEntityMap) {
DescriptionReferenceImportExport xml = new DescriptionReferenceImportExport();
if (entity == null) return xml;
@ -1382,7 +1435,8 @@ public class DescriptionServiceImpl implements DescriptionService {
DescriptionPersist persist = new DescriptionPersist();
persist.setLabel(descriptionXml.getLabel());
persist.setDescription(descriptionXml.getDescription());
persist.setStatus(DescriptionStatus.Draft);
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().isActive(IsActive.Active).internalStatuses(DescriptionStatus.Draft).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
persist.setPlanId(planId);
persist.setDescriptionTemplateId(this.xmlToDescriptionTemplatePersist(descriptionXml));
persist.setPlanDescriptionTemplateId(this.xmlToPlanDescriptionTemplatePersist(descriptionXml, planId));
@ -1598,7 +1652,8 @@ public class DescriptionServiceImpl implements DescriptionService {
DescriptionPersist persist = new DescriptionPersist();
persist.setLabel(model.getLabel());
persist.setDescription(model.getDescription());
persist.setStatus(DescriptionStatus.Draft);
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().isActive(IsActive.Active).internalStatuses(DescriptionStatus.Draft).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
persist.setPlanId(planId);
persist.setDescriptionTemplateId(this.commonModelToDescriptionTemplatePersist(model));
persist.setPlanDescriptionTemplateId(this.commonModelTToPlanDescriptionTemplatePersist(model, planId));

View File

@ -10,6 +10,8 @@ import org.opencdmp.model.descriptionstatus.DescriptionStatus;
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
import javax.management.InvalidApplicationException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public interface DescriptionStatusService {
@ -17,4 +19,6 @@ public interface DescriptionStatusService {
DescriptionStatus persist(DescriptionStatusPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
Map<UUID, List<UUID>> getAuthorizedAvailableStatusIds(List<UUID> descriptionsIds);
}

View File

@ -3,6 +3,7 @@ package org.opencdmp.service.descriptionstatus;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
@ -12,22 +13,33 @@ import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import jakarta.xml.bind.JAXBException;
import org.opencdmp.authorization.AffiliatedResource;
import org.opencdmp.authorization.Permission;
import org.opencdmp.authorization.authorizationcontentresolver.AuthorizationContentResolver;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionAuthorizationEntity;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionAuthorizationItemEntity;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionTransitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionStatusEntity;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.*;
import org.opencdmp.event.DescriptionStatusTouchedEvent;
import org.opencdmp.event.EventBroker;
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
import org.opencdmp.model.deleter.DescriptionStatusDeleter;
import org.opencdmp.model.description.Description;
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionAuthorizationItemPersist;
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionAuthorizationPersist;
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionPersist;
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
import org.opencdmp.query.DescriptionQuery;
import org.opencdmp.query.DescriptionStatusQuery;
import org.opencdmp.service.custompolicy.CustomPolicyService;
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
@ -35,8 +47,8 @@ import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class DescriptionStatusServiceImpl implements DescriptionStatusService {
@ -51,8 +63,15 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
private final ConventionService conventionService;
private final MessageSource messageSource;
private final XmlHandlingService xmlHandlingService;
private final EventBroker eventBroker;
private final TenantScope tenantScope;
private final DescriptionWorkflowService descriptionWorkflowService;
private final CustomPolicyService customPolicyService;
private final AuthorizationService authorizationService;
private final AuthorizationContentResolver authorizationContentResolver;
private final QueryFactory queryFactory;
public DescriptionStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authService, TenantEntityManager entityManager, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService) {
public DescriptionStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authService, TenantEntityManager entityManager, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService, EventBroker eventBroker, TenantScope tenantScope, DescriptionWorkflowService descriptionWorkflowService, CustomPolicyService customPolicyService, AuthorizationService authorizationService, AuthorizationContentResolver authorizationContentResolver, QueryFactory queryFactory) {
this.builderFactory = builderFactory;
this.deleterFactory = deleterFactory;
@ -61,6 +80,13 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
this.conventionService = conventionService;
this.messageSource = messageSource;
this.xmlHandlingService = xmlHandlingService;
this.eventBroker = eventBroker;
this.tenantScope = tenantScope;
this.descriptionWorkflowService = descriptionWorkflowService;
this.customPolicyService = customPolicyService;
this.authorizationService = authorizationService;
this.authorizationContentResolver = authorizationContentResolver;
this.queryFactory = queryFactory;
}
@ -86,6 +112,7 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
data.setName(model.getName());
data.setDescription(model.getDescription());
data.setAction(model.getAction());
data.setInternalStatus(model.getInternalStatus());
data.setDefinition(this.xmlHandlingService.toXml(this.buildDescriptionStatusDefinitionEntity(model.getDefinition())));
data.setUpdatedAt(Instant.now());
@ -97,6 +124,8 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
this.entityManager.flush();
this.eventBroker.emit(new DescriptionStatusTouchedEvent(data.getId(), this.tenantScope.getTenantCode()));
return this.builderFactory.builder(DescriptionStatusBuilder.class).build(BaseFieldSet.build(fields, DescriptionStatus._id), data);
}
@ -115,7 +144,7 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
return data;
data.setAuthorization(this.buildDescriptionStatusDefinitionAuthorizationEntity(persist.getAuthorization()));
if (!this.conventionService.isListNullOrEmpty(persist.getAvailableActions())) data.setAvailableActions(persist.getAvailableActions());
return data;
}
@ -141,4 +170,34 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
return data;
}
@Override
public Map<UUID, List<UUID>> getAuthorizedAvailableStatusIds(List<UUID> descriptionsIds) {
Map<UUID, List<UUID>> authorizedStatusMap = new HashMap<>();
DescriptionWorkflowDefinitionEntity definition;
try {
definition = this.descriptionWorkflowService.getWorkFlowDefinition();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
List<DescriptionEntity> descriptionEntities = this.queryFactory.query(DescriptionQuery.class).ids(descriptionsIds).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(Description._id).ensure(Description._status).ensure(Description._plan));
List<DescriptionStatusEntity> statusEntities = this.queryFactory.query(DescriptionStatusQuery.class).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(DescriptionStatus._id));
for (DescriptionEntity description: descriptionEntities) {
authorizedStatusMap.put(description.getId(), new ArrayList<>());
AffiliatedResource affiliatedResource = this.authorizationContentResolver.planAffiliation(description.getPlanId());
for (DescriptionStatusEntity status: statusEntities) {
List<DescriptionWorkflowDefinitionTransitionEntity> availableTransitions = definition.getStatusTransitions().stream().filter(x -> x.getFromStatusId().equals(description.getStatusId())).collect(Collectors.toList());
if (availableTransitions.stream().filter(x -> x.getToStatusId().equals(status.getId())).findFirst().orElse(null) != null) {
String editPermission = this.customPolicyService.getDescriptionStatusCanEditStatusPermission(status.getId());
Boolean isAllowed = affiliatedResource == null ? this.authorizationService.authorize(editPermission) : this.authorizationService.authorizeAtLeastOne(List.of(affiliatedResource), editPermission);
if (isAllowed) authorizedStatusMap.get(description.getId()).add(status.getId());
}
}
}
return authorizedStatusMap;
}
}

View File

@ -1,6 +1,7 @@
package org.opencdmp.service.descriptionworkflow;
import gr.cite.tools.fieldset.FieldSet;
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowPersist;
@ -11,4 +12,6 @@ public interface DescriptionWorkflowService {
DescriptionWorkflow persist(DescriptionWorkflowPersist persist, FieldSet fields) throws InvalidApplicationException;
void deleteAndSave(UUID id) throws InvalidApplicationException;
DescriptionWorkflowDefinitionEntity getWorkFlowDefinition() throws InvalidApplicationException;
}

View File

@ -3,15 +3,19 @@ package org.opencdmp.service.descriptionworkflow;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.authorization.Permission;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionTransitionEntity;
import org.opencdmp.convention.ConventionService;
@ -24,6 +28,7 @@ import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowDefinitionPersist;
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowDefinitionTransitionPersist;
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowPersist;
import org.opencdmp.query.DescriptionWorkflowQuery;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
@ -48,8 +53,10 @@ public class DescriptionWorkflowServiceImpl implements DescriptionWorkflowServic
private final TenantEntityManager entityManager;
private final MessageSource messageSource;
private final ErrorThesaurusProperties errors;
private final TenantScope tenantScope;
private final QueryFactory queryFactory;
public DescriptionWorkflowServiceImpl(AuthorizationService authService, ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory, DeleterFactory deleterFactory, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors) {
public DescriptionWorkflowServiceImpl(AuthorizationService authService, ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory, DeleterFactory deleterFactory, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors, TenantScope tenantScope, QueryFactory queryFactory) {
this.authService = authService;
this.conventionService = conventionService;
this.xmlHandlingService = xmlHandlingService;
@ -58,6 +65,8 @@ public class DescriptionWorkflowServiceImpl implements DescriptionWorkflowServic
this.entityManager = entityManager;
this.messageSource = messageSource;
this.errors = errors;
this.tenantScope = tenantScope;
this.queryFactory = queryFactory;
}
@ -132,4 +141,37 @@ public class DescriptionWorkflowServiceImpl implements DescriptionWorkflowServic
return data;
}
@Override
public DescriptionWorkflowDefinitionEntity getWorkFlowDefinition() throws InvalidApplicationException {
DescriptionWorkflowQuery query = this.queryFactory.query(DescriptionWorkflowQuery.class).authorize(AuthorizationFlags.AllExceptPublic).isActives(IsActive.Active);
if (this.tenantScope.isDefaultTenant()) query = query.defaultTenant(true);
List<DescriptionWorkflowEntity> descriptionWorkflowEntities = query.collect();
if (this.conventionService.isListNullOrEmpty(descriptionWorkflowEntities)) throw new MyApplicationException("Description workflows not found!");
DescriptionWorkflowEntity entity = null;
if (!this.tenantScope.isDefaultTenant()) {
entity = descriptionWorkflowEntities.stream().filter(x -> {
try {
return (this.tenantScope.getTenant().equals(x.getTenantId()));
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
}).findFirst().orElse(null);
}
// fallback to default tenant
if (entity == null) {
entity = descriptionWorkflowEntities.stream().filter(x -> x.getTenantId() == null).findFirst().orElse(null);
}
if (entity == null) throw new MyApplicationException("Description workflow not found!");
DescriptionWorkflowDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(DescriptionWorkflowDefinitionEntity.class, entity.getDefinition());
if (definition == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{entity.getId(), DescriptionWorkflowDefinitionEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
return definition;
}
}

View File

@ -136,7 +136,7 @@ public class ElasticServiceImpl implements ElasticService {
propertyMap.put(DescriptionElasticEntity._tenantId, this.createElastic(FieldType.Keyword, false));
propertyMap.put(DescriptionElasticEntity._label, this.createElastic(FieldType.Text, true));
propertyMap.put(DescriptionElasticEntity._description, this.createElastic(FieldType.Text, true));
propertyMap.put(DescriptionElasticEntity._status, this.createElastic(FieldType.Short, false));
propertyMap.put(DescriptionElasticEntity._statusId, this.createElastic(FieldType.Keyword, false));
propertyMap.put(DescriptionElasticEntity._finalizedAt, this.createElastic(FieldType.Date, false));
propertyMap.put(DescriptionElasticEntity._createdAt, this.createElastic(FieldType.Date, false));
propertyMap.put(DescriptionElasticEntity._updatedAt, this.createElastic(FieldType.Date, false));
@ -154,7 +154,7 @@ public class ElasticServiceImpl implements ElasticService {
propertyMap.put(PlanElasticEntity._tenantId, this.createElastic(FieldType.Keyword, false));
propertyMap.put(PlanElasticEntity._label, this.createElastic(FieldType.Text, true));
propertyMap.put(PlanElasticEntity._description, this.createElastic(FieldType.Text, false));
propertyMap.put(PlanElasticEntity._status, this.createElastic(FieldType.Short, false));
propertyMap.put(PlanElasticEntity._statusId, this.createElastic(FieldType.Keyword, false));
propertyMap.put(PlanElasticEntity._version, this.createElastic(FieldType.Short, false));
propertyMap.put(PlanElasticEntity._language, this.createElastic(FieldType.Keyword, false));
propertyMap.put(PlanElasticEntity._blueprintId, this.createElastic(FieldType.Keyword, false));
@ -230,7 +230,7 @@ public class ElasticServiceImpl implements ElasticService {
propertyMap.put(NestedPlanElasticEntity._id, this.createElastic(FieldType.Keyword, false));
propertyMap.put(NestedPlanElasticEntity._label, this.createElastic(FieldType.Text, true));
propertyMap.put(NestedPlanElasticEntity._description, this.createElastic(FieldType.Text, false));
propertyMap.put(NestedPlanElasticEntity._status, this.createElastic(FieldType.Short, false));
propertyMap.put(NestedPlanElasticEntity._statusId, this.createElastic(FieldType.Keyword, false));
propertyMap.put(NestedPlanElasticEntity._version, this.createElastic(FieldType.Short, false));
propertyMap.put(NestedPlanElasticEntity._versionStatus, this.createElastic(FieldType.Short, false));
propertyMap.put(NestedPlanElasticEntity._language, this.createElastic(FieldType.Keyword, false));

View File

@ -268,7 +268,8 @@ public class FileTransformerServiceImpl implements FileTransformerService {
} else {
try {
this.entityManager.disableTenantFilters();
entity = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(planId).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public).first();
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
entity = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(planId).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();
@ -307,7 +308,8 @@ public class FileTransformerServiceImpl implements FileTransformerService {
} else {
try {
this.entityManager.disableTenantFilters();
entity = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(descriptionId).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public)).first();
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
entity = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(descriptionId).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public)).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();

View File

@ -325,21 +325,24 @@ public class MetricsServiceImpl implements MetricsService {
}
private double calculateDraftDmps(boolean forNexus) {
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().statuses(PlanStatus.Draft).isActive(IsActive.Active);
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Draft).isActives(IsActive.Active);
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().planStatusSubQuery(statusQuery).isActive(IsActive.Active);
if (forNexus)
planQuery.after(this._config.getNexusDate());
return planQuery.count();
}
private double calculateFinalizedDmps(boolean forNexus) {
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().statuses(PlanStatus.Finalized).isActive(IsActive.Active);
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().planStatusSubQuery(statusQuery).isActive(IsActive.Active);
if (forNexus)
planQuery.after(this._config.getNexusDate());
return planQuery.count();
}
private double calculatePublishedDmps(boolean forNexus) {
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public).isActive(IsActive.Active);
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public).isActive(IsActive.Active);
if (forNexus)
planQuery.after(this._config.getNexusDate());
return planQuery.count();
@ -355,8 +358,10 @@ public class MetricsServiceImpl implements MetricsService {
return planQuery.count();
}
private double calculateDraftDmpsWithGrant(boolean forNexus) {
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).statuses(PlanStatus.Draft).disableTracking().isActive(IsActive.Active);
private double calculateDraftDmpsWithGrant(boolean forNexus)
{
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Draft).isActives(IsActive.Active);
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).planStatusSubQuery(statusQuery).disableTracking().isActive(IsActive.Active);
if (forNexus)
planQuery.after(this._config.getNexusDate());
ReferenceQuery referenceQuery = this.queryFactory.query(ReferenceQuery.class).disableTracking().typeIds(this._config.getReferenceTypes().getGrantIds()).isActive(IsActive.Active);
@ -366,7 +371,8 @@ public class MetricsServiceImpl implements MetricsService {
}
private double calculateFinalizedDmpsWithGrant(boolean forNexus) {
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().statuses(PlanStatus.Finalized).isActive(IsActive.Active);
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking().planStatusSubQuery(statusQuery).isActive(IsActive.Active);
if (forNexus)
planQuery.after(this._config.getNexusDate());
ReferenceQuery referenceQuery = this.queryFactory.query(ReferenceQuery.class).disableTracking().typeIds(this._config.getReferenceTypes().getGrantIds()).isActive(IsActive.Active);
@ -376,7 +382,8 @@ public class MetricsServiceImpl implements MetricsService {
}
private double calculatePublishedDmpsWithGrant(boolean forNexus) {
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).statuses(PlanStatus.Finalized).disableTracking().accessTypes(PlanAccessType.Public).isActive(IsActive.Active);
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).planStatusSubQuery(statusQuery).disableTracking().accessTypes(PlanAccessType.Public).isActive(IsActive.Active);
if (forNexus)
planQuery.after(this._config.getNexusDate());
ReferenceQuery referenceQuery = this.queryFactory.query(ReferenceQuery.class).disableTracking().typeIds(this._config.getReferenceTypes().getGrantIds()).isActive(IsActive.Active);
@ -426,30 +433,35 @@ public class MetricsServiceImpl implements MetricsService {
}
private double calculateDraftDatasets(boolean forNexus) {
DescriptionQuery descriptionQuery = this.queryFactory.query(DescriptionQuery.class).disableTracking().statuses(DescriptionStatus.Draft).isActive(IsActive.Active);
DescriptionStatusQuery descriptionStatusQuery = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Draft).isActive(IsActive.Active);
DescriptionQuery descriptionQuery = this.queryFactory.query(DescriptionQuery.class).disableTracking().descriptionStatusSubQuery(descriptionStatusQuery).isActive(IsActive.Active);
if (forNexus)
descriptionQuery.createdAfter(this._config.getNexusDate());
return descriptionQuery.count();
}
private double calculateFinalizedDatasets(boolean forNexus) {
DescriptionQuery descriptionQuery = this.queryFactory.query(DescriptionQuery.class).disableTracking().statuses(DescriptionStatus.Finalized).isActive(IsActive.Active);
DescriptionStatusQuery descriptionStatusQuery = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active);
DescriptionQuery descriptionQuery = this.queryFactory.query(DescriptionQuery.class).disableTracking().descriptionStatusSubQuery(descriptionStatusQuery).isActive(IsActive.Active);
if (forNexus)
descriptionQuery.createdAfter(this._config.getNexusDate());
return descriptionQuery.count();
}
private double calculatePublishedDatasets(boolean forNexus) {
DescriptionQuery descriptionQuery = this.queryFactory.query(DescriptionQuery.class).disableTracking().statuses(DescriptionStatus.Finalized).isActive(IsActive.Active);
DescriptionStatusQuery descriptionStatusQuery = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active);
DescriptionQuery descriptionQuery = this.queryFactory.query(DescriptionQuery.class).disableTracking().descriptionStatusSubQuery(descriptionStatusQuery).isActive(IsActive.Active);
if (forNexus)
descriptionQuery.createdAfter(this._config.getNexusDate());
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).disableTracking().statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public);
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).disableTracking().planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public);
descriptionQuery.planSubQuery(planQuery);
return descriptionQuery.count();
}
private double calculateDoiedDatasets(boolean forNexus) {
DescriptionQuery descriptionQuery = this.queryFactory.query(DescriptionQuery.class).disableTracking().statuses(DescriptionStatus.Finalized).isActive(IsActive.Active);
DescriptionStatusQuery descriptionStatusQuery = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active);
DescriptionQuery descriptionQuery = this.queryFactory.query(DescriptionQuery.class).disableTracking().descriptionStatusSubQuery(descriptionStatusQuery).isActive(IsActive.Active);
if (forNexus)
descriptionQuery.createdAfter(this._config.getNexusDate());
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active);

View File

@ -34,9 +34,7 @@ public interface PlanService {
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException;
void finalize(UUID id, List<UUID> descriptionIds) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException;
void undoFinalize(UUID id, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException;
void setStatus(UUID id, UUID newStatusId, List<UUID> descriptionIds) throws InvalidApplicationException, IOException;
PlanValidationResult validate(UUID id) throws InvalidApplicationException;

View File

@ -96,11 +96,14 @@ import org.opencdmp.model.referencetype.ReferenceType;
import org.opencdmp.query.*;
import org.opencdmp.service.accounting.AccountingService;
import org.opencdmp.service.actionconfirmation.ActionConfirmationService;
import org.opencdmp.service.custompolicy.CustomPolicyService;
import org.opencdmp.service.description.DescriptionService;
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
import org.opencdmp.service.elastic.ElasticService;
import org.opencdmp.service.filetransformer.FileTransformerService;
import org.opencdmp.service.planblueprint.PlanBlueprintService;
import org.opencdmp.service.planworkflow.PlanWorkflowServiceImpl;
import org.opencdmp.service.responseutils.ResponseUtilsService;
import org.opencdmp.service.usagelimit.UsageLimitService;
import org.slf4j.LoggerFactory;
@ -183,6 +186,9 @@ public class PlanServiceImpl implements PlanService {
private final PlanBlueprintService planBlueprintService;
private final UsageLimitService usageLimitService;
private final AccountingService accountingService;
private final DescriptionWorkflowService descriptionWorkflowService;
private final PlanWorkflowServiceImpl planWorkflowService;
private final CustomPolicyService customPolicyService;
@Autowired
public PlanServiceImpl(
@ -205,7 +211,7 @@ public class PlanServiceImpl implements PlanService {
FileTransformerService fileTransformerService,
ValidatorFactory validatorFactory,
ElasticService elasticService, DescriptionTemplateService descriptionTemplateService,
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService, UsageLimitService usageLimitService, AccountingService accountingService) {
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService, PlanWorkflowServiceImpl planWorkflowService, CustomPolicyService customPolicyService) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -234,6 +240,9 @@ public class PlanServiceImpl implements PlanService {
this.planBlueprintService = planBlueprintService;
this.usageLimitService = usageLimitService;
this.accountingService = accountingService;
this.descriptionWorkflowService = descriptionWorkflowService;
this.planWorkflowService = planWorkflowService;
this.customPolicyService = customPolicyService;
}
public Plan persist(PlanPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, IOException {
@ -308,6 +317,9 @@ public class PlanServiceImpl implements PlanService {
}
private void sendNotification(PlanEntity plan) throws InvalidApplicationException {
PlanStatusEntity planStatusEntity = this.entityManager.find(PlanStatusEntity.class, plan.getStatusId(), true);
if (planStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{plan.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
List<PlanUserEntity> existingUsers = this.queryFactory.query(PlanUserQuery.class).disableTracking()
.planIds(plan.getId())
.isActives(IsActive.Active)
@ -321,22 +333,25 @@ public class PlanServiceImpl implements PlanService {
if (!planUser.getUserId().equals(this.userScope.getUserIdSafe())){
UserEntity user = this.queryFactory.query(UserQuery.class).disableTracking().ids(planUser.getUserId()).first();
if (user == null || user.getIsActive().equals(IsActive.Inactive)) throw new MyValidationException(this.errors.getPlanInactiveUser().getCode(), this.errors.getPlanInactiveUser().getMessage());
this.createPlanNotificationEvent(plan, user);
this.createPlanNotificationEvent(plan, planStatusEntity, user);
}
}
}
private void createPlanNotificationEvent(PlanEntity plan, UserEntity user) throws InvalidApplicationException {
private void createPlanNotificationEvent(PlanEntity plan, PlanStatusEntity planStatus, UserEntity user) throws InvalidApplicationException {
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
event.setUserId(user.getId());
this.applyNotificationType(plan.getStatus(), event);
if (planStatus.getInternalStatus() == null) event.setNotificationType(this.notificationProperties.getPlanStatusChangedType());
else this.applyNotificationType(planStatus.getInternalStatus(), event);
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));
fieldInfoList.add(new FieldInfo("{reasonName}", DataType.String, this.queryFactory.query(UserQuery.class).disableTracking().ids(this.userScope.getUserId()).first().getName()));
fieldInfoList.add(new FieldInfo("{name}", DataType.String, plan.getLabel()));
fieldInfoList.add(new FieldInfo("{id}", DataType.String, plan.getId().toString()));
if (planStatus.getInternalStatus() == null) fieldInfoList.add(new FieldInfo("{statusName}", DataType.String, planStatus.getName()));
if(this.tenantScope.getTenantCode() != null && !this.tenantScope.getTenantCode().equals(this.tenantScope.getDefaultTenantCode())){
fieldInfoList.add(new FieldInfo("{tenant-url-path}", DataType.String, String.format("/t/%s", this.tenantScope.getTenantCode())));
}
@ -380,7 +395,10 @@ public class PlanServiceImpl implements PlanService {
planQuery.setOrder(new Ordering().addDescending(Plan._version));
previousPlan = planQuery.count() > 0 ? planQuery.collect().getFirst() : null;
if (previousPlan != null){
if (previousPlan.getStatus().equals(PlanStatus.Finalized)) previousPlan.setVersionStatus(PlanVersionStatus.Current);
PlanStatusEntity previousPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, previousPlan.getStatusId(), true);
if (previousPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{previousPlan.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (previousPlanStatusEntity.getInternalStatus() != null && previousPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) previousPlan.setVersionStatus(PlanVersionStatus.Current);
else previousPlan.setVersionStatus(PlanVersionStatus.NotFinalized);
this.entityManager.merge(previousPlan);
}
@ -422,6 +440,9 @@ public class PlanServiceImpl implements PlanService {
.count();
if (notFinalizedCount > 0) throw new MyValidationException(this.errors.getPlanNewVersionAlreadyCreatedDraft().getCode(), this.errors.getPlanNewVersionAlreadyCreatedDraft().getMessage());
PlanStatusEntity startingPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, this.planWorkflowService.getWorkFlowDefinition().getStartingStatusId(), true);
if (startingPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{this.planWorkflowService.getWorkFlowDefinition().getStartingStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
PlanEntity newPlan = new PlanEntity();
newPlan.setId(UUID.randomUUID());
newPlan.setIsActive(IsActive.Active);
@ -434,6 +455,7 @@ public class PlanServiceImpl implements PlanService {
newPlan.setLabel(model.getLabel());
newPlan.setLanguage(oldPlanEntity.getLanguage());
newPlan.setStatus(PlanStatus.Draft);
newPlan.setStatusId(startingPlanStatusEntity.getId());
newPlan.setProperties(oldPlanEntity.getProperties());
newPlan.setBlueprintId(model.getBlueprintId());
newPlan.setAccessType(oldPlanEntity.getAccessType());
@ -585,7 +607,7 @@ public class PlanServiceImpl implements PlanService {
this.entityManager.flush();
this.updateVersionStatusAndSave(newPlan, PlanStatus.Draft, newPlan.getStatus());
this.updateVersionStatusAndSave(newPlan, PlanStatus.Draft, startingPlanStatusEntity.getInternalStatus());
this.entityManager.flush();
@ -620,6 +642,7 @@ public class PlanServiceImpl implements PlanService {
newDescription.setLabel(existing.getLabel());
newDescription.setDescription(existing.getDescription());
newDescription.setStatus(DescriptionStatus.Draft);
newDescription.setStatusId(this.descriptionWorkflowService.getWorkFlowDefinition().getStartingStatusId());
newDescription.setProperties(existing.getProperties());
newDescription.setPlanId(planId);
if (newPlanDescriptionTemplateId == null && planDescriptionTemplateRemap != null) newDescription.setPlanDescriptionTemplateId(planDescriptionTemplateRemap.get(existing.getPlanDescriptionTemplateId()));
@ -692,7 +715,8 @@ public class PlanServiceImpl implements PlanService {
List<TagEntity> tags = new ArrayList<>();
try {
this.entityManager.disableTenantFilters();
existing = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(descriptionId).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public)).first();
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
existing = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(descriptionId).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public)).first();
if (existing == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
@ -740,6 +764,7 @@ public class PlanServiceImpl implements PlanService {
newDescription.setLabel(existing.getLabel());
newDescription.setDescription(existing.getDescription());
newDescription.setStatus(DescriptionStatus.Draft);
newDescription.setStatusId(this.descriptionWorkflowService.getWorkFlowDefinition().getStartingStatusId());
newDescription.setProperties(existing.getProperties());
newDescription.setPlanId(planId);
if (planDescriptionTemplateRemap != null) newDescription.setPlanDescriptionTemplateId(planDescriptionTemplateRemap.get(existing.getPlanDescriptionTemplateId()));
@ -847,9 +872,11 @@ public class PlanServiceImpl implements PlanService {
private void updateVersionStatusAndSave(PlanEntity data, PlanStatus previousStatus, PlanStatus newStatus) throws InvalidApplicationException {
if (previousStatus.equals(newStatus))
if (previousStatus == null && newStatus == null)
return;
if (previousStatus.equals(PlanStatus.Finalized) && newStatus.equals(PlanStatus.Draft)){
if (previousStatus != null && previousStatus.equals(newStatus))
return;
if (previousStatus != null && previousStatus.equals(PlanStatus.Finalized) && (newStatus == null || newStatus.equals(PlanStatus.Draft))){
boolean alreadyCreatedNewVersion = this.queryFactory.query(PlanQuery.class).disableTracking()
.versionStatuses(PlanVersionStatus.NotFinalized, PlanVersionStatus.Current)
.excludedIds(data.getId())
@ -862,7 +889,7 @@ public class PlanServiceImpl implements PlanService {
this.entityManager.merge(data);
}
if (newStatus.equals(PlanStatus.Finalized)) {
if (newStatus != null && newStatus.equals(PlanStatus.Finalized)) {
List<PlanEntity> latestVersionPlans = this.queryFactory.query(PlanQuery.class)
.versionStatuses(PlanVersionStatus.Current).excludedIds(data.getId())
.isActive(IsActive.Active).groupIds(data.getGroupId()).collect();
@ -907,6 +934,7 @@ public class PlanServiceImpl implements PlanService {
newPlan.setLabel(model.getLabel());
newPlan.setLanguage(existingPlanEntity.getLanguage());
newPlan.setStatus(PlanStatus.Draft);
newPlan.setStatusId(this.planWorkflowService.getWorkFlowDefinition().getStartingStatusId());
newPlan.setProperties(existingPlanEntity.getProperties());
newPlan.setBlueprintId(existingPlanEntity.getBlueprintId());
newPlan.setAccessType(existingPlanEntity.getAccessType());
@ -1018,7 +1046,8 @@ public class PlanServiceImpl implements PlanService {
try {
this.entityManager.disableTenantFilters();
// query for public plan
existingPlanEntity = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(model.getId()).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public).firstAs(fields);
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
existingPlanEntity = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(model.getId()).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public).firstAs(fields);
if (existingPlanEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), PublicPlan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
@ -1095,6 +1124,7 @@ public class PlanServiceImpl implements PlanService {
newPlan.setLabel(model.getLabel());
newPlan.setLanguage(existingPlanEntity.getLanguage());
newPlan.setStatus(PlanStatus.Draft);
newPlan.setStatusId(this.planWorkflowService.getWorkFlowDefinition().getStartingStatusId());
newPlan.setProperties(existingPlanEntity.getProperties());
newPlan.setBlueprintId(blueprintEntityByTenant.getId());
newPlan.setAccessType(existingPlanEntity.getAccessType());
@ -1273,6 +1303,7 @@ public class PlanServiceImpl implements PlanService {
PlanEntity data = this.entityManager.find(PlanEntity.class, model.getPlanId(), true);
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (data.getIsActive().equals(IsActive.Inactive)) throw new MyApplicationException("Plan is not Active");
List<PlanUserEntity> existingUsers = this.queryFactory.query(PlanUserQuery.class)
.planIds(model.getPlanId()).ids(model.getId()).userRoles(model.getRole())
.collect();
@ -1309,9 +1340,13 @@ public class PlanServiceImpl implements PlanService {
data = this.entityManager.find(PlanEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
if (model.getStatus() != null && model.getStatus() == PlanStatus.Finalized && data.getStatus() != PlanStatus.Finalized) {
PlanStatusEntity oldPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, data.getStatusId(), true);
if (oldPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
PlanStatusEntity newPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, model.getStatusId(), true);
if (newPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (newPlanStatusEntity.getInternalStatus() != null && newPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized) && oldPlanStatusEntity.getInternalStatus() != null && oldPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(model.getId())), Permission.FinalizePlan);
data.setStatus(model.getStatus());
data.setStatusId(model.getStatusId());
data.setFinalizedAt(Instant.now());
}
} else {
@ -1320,13 +1355,14 @@ public class PlanServiceImpl implements PlanService {
data.setGroupId(UUID.randomUUID());
data.setVersion((short) 1);
data.setStatus(PlanStatus.Draft);
data.setStatusId(this.planWorkflowService.getWorkFlowDefinition().getStartingStatusId());
data.setVersionStatus(PlanVersionStatus.NotFinalized);
data.setCreatorId(this.userScope.getUserId());
data.setBlueprintId(model.getBlueprint());
data.setIsActive(IsActive.Active);
data.setCreatedAt(Instant.now());
}
PlanStatus previousStatus = data.getStatus();
// PlanStatus previousStatus = data.getStatus();
PlanBlueprintEntity planBlueprintEntity = this.entityManager.find(PlanBlueprintEntity.class, model.getBlueprint(), true);
if (planBlueprintEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getBlueprint(), PlanBlueprint.class.getSimpleName()}, LocaleContextHolder.getLocale()));
@ -1348,7 +1384,7 @@ public class PlanServiceImpl implements PlanService {
this.entityManager.flush();
this.updateVersionStatusAndSave(data, previousStatus, data.getStatus());
// this.updateVersionStatusAndSave(data, previousStatus, data.getStatus());
this.entityManager.flush();
@ -1574,51 +1610,88 @@ public class PlanServiceImpl implements PlanService {
return data;
}
public void finalize(UUID id, List<UUID> descriptionIds) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(id)), Permission.FinalizePlan);
public void setStatus(UUID id, UUID newStatusId, List<UUID> descriptionIds) throws InvalidApplicationException, IOException {
PlanEntity plan = this.queryFactory.query(PlanQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(id).isActive(IsActive.Active).first();
if (plan == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (plan == null){
throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
try {
this.authorizationService.authorizeForce(this.customPolicyService.getPlanStatusCanEditStatusPermission(newStatusId));
} catch (Exception e) {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(id)), this.customPolicyService.getPlanStatusCanEditStatusPermission(newStatusId));
}
if (plan.getStatus().equals(PlanStatus.Finalized)){
if (plan.getStatusId().equals(newStatusId)) throw new MyApplicationException("Old status equals with new");
PlanStatusEntity oldPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, plan.getStatusId(), true);
if (oldPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{plan.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
PlanStatusEntity newPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, newStatusId, true);
if (newPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{newStatusId, PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (oldPlanStatusEntity.getInternalStatus() != null && oldPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) {
this.undoFinalize(plan, oldPlanStatusEntity, newPlanStatusEntity);
} else if (newPlanStatusEntity.getInternalStatus() != null && newPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) {
this.finalize(plan, descriptionIds ,oldPlanStatusEntity, newPlanStatusEntity);
} else {
plan.setStatusId(newPlanStatusEntity.getId());
plan.setUpdatedAt(Instant.now());
this.entityManager.merge(plan);
this.entityManager.flush();
this.sendNotification(plan);
}
}
private void finalize(PlanEntity plan, List<UUID> descriptionIds, PlanStatusEntity oldPlanStatusEntity, PlanStatusEntity newPlanStatusEntity) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(plan.getId())), Permission.FinalizePlan);
if (oldPlanStatusEntity.getInternalStatus() != null && oldPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)){
throw new MyApplicationException("Plan is already finalized");
}
if (this.validate(id).getResult().equals(PlanValidationOutput.Invalid)){
if (this.validate(plan.getId()).getResult().equals(PlanValidationOutput.Invalid)){
throw new MyApplicationException("Plan is invalid");
}
List<DescriptionEntity> descriptions = this.queryFactory.query(DescriptionQuery.class)
.authorize(AuthorizationFlags.AllExceptPublic).planIds(id).isActive(IsActive.Active).collect();
.authorize(AuthorizationFlags.AllExceptPublic).planIds(plan.getId()).isActive(IsActive.Active).collect();
if (!this.conventionService.isListNullOrEmpty(descriptions)) {
List<DescriptionStatusEntity> statusEntities = this.queryFactory.query(DescriptionStatusQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(descriptions.stream().map(DescriptionEntity::getStatusId).distinct().toList()).isActive(IsActive.Active).collect();
if (this.conventionService.isListNullOrEmpty(statusEntities)) throw new MyApplicationException("Not found description statuses");
DescriptionStatusEntity descriptionFinalizedStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
if (descriptionFinalizedStatusEntity == null) throw new MyApplicationException("finalized status not found");
DescriptionStatusEntity canceledStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Canceled).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
if (canceledStatusEntity == null) throw new MyApplicationException("canceled status not found");
for (DescriptionEntity description: descriptions) {
DescriptionStatusEntity currentStatusEntity = statusEntities.stream().filter(x -> x.getId().equals(description.getStatusId())).findFirst().orElse(null);
if (descriptionIds.contains(description.getId())){
// description to be finalized
if (description.getStatus().equals(DescriptionStatus.Finalized)){
if (currentStatusEntity != null && currentStatusEntity.getInternalStatus()!= null && currentStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)){
throw new MyApplicationException("Description is already finalized");
}
if (this.descriptionService.validate(List.of(description.getId())).getFirst().getResult().equals(DescriptionValidationOutput.Invalid)){
throw new MyApplicationException("Description is invalid");
}
description.setStatus(DescriptionStatus.Finalized);
description.setStatusId(descriptionFinalizedStatusEntity.getId());
description.setUpdatedAt(Instant.now());
description.setFinalizedAt(Instant.now());
this.entityManager.merge(description);
} else if (description.getStatus().equals(DescriptionStatus.Draft)) {
} else if (currentStatusEntity != null && currentStatusEntity.getInternalStatus()!= null && !currentStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) {
// description to be canceled
description.setStatus(DescriptionStatus.Canceled);
this.deleterFactory.deleter(DescriptionDeleter.class).delete(List.of(description), true);
description.setStatusId(canceledStatusEntity.getId());
this.deleterFactory.deleter(DescriptionDeleter.class).delete(List.of(description), false);
}
}
}
PlanStatus previousStatus = plan.getStatus();
plan.setStatus(PlanStatus.Finalized);
plan.setStatusId(newPlanStatusEntity.getId());
plan.setUpdatedAt(Instant.now());
plan.setFinalizedAt(Instant.now());
this.updateVersionStatusAndSave(plan, previousStatus, plan.getStatus());
this.updateVersionStatusAndSave(plan, oldPlanStatusEntity.getInternalStatus(), newPlanStatusEntity.getInternalStatus());
plan.setVersionStatus(PlanVersionStatus.Current);
this.entityManager.merge(plan);
@ -1630,24 +1703,21 @@ public class PlanServiceImpl implements PlanService {
this.sendNotification(plan);
}
public void undoFinalize(UUID id, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(id)), Permission.UndoFinalizePlan);
PlanEntity plan = this.queryFactory.query(PlanQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(id).isActive(IsActive.Active).firstAs(fields);
private void undoFinalize(PlanEntity plan, PlanStatusEntity oldPlanStatusEntity, PlanStatusEntity newPlanStatusEntity) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(plan.getId())), Permission.UndoFinalizePlan);
if (plan == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!plan.getStatus().equals(PlanStatus.Finalized)) throw new MyApplicationException("Plan is already drafted");
if (oldPlanStatusEntity.getInternalStatus() == null && !oldPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) throw new MyApplicationException("Plan is already non finalized");
EntityDoiQuery entityDoiQuery = this.queryFactory.query(EntityDoiQuery.class).types(EntityType.Plan).entityIds(plan.getId()).isActive(IsActive.Active);
if (entityDoiQuery.count() > 0) throw new MyApplicationException("Plan is deposited");
plan.setStatus(PlanStatus.Draft);
plan.setStatusId(newPlanStatusEntity.getId());
plan.setUpdatedAt(Instant.now());
this.entityManager.merge(plan);
this.entityManager.flush();
this.updateVersionStatusAndSave(plan, PlanStatus.Finalized, plan.getStatus());
this.updateVersionStatusAndSave(plan, PlanStatus.Finalized, newPlanStatusEntity.getInternalStatus());
this.entityManager.flush();
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking()
@ -1659,7 +1729,10 @@ public class PlanServiceImpl implements PlanService {
planQuery.setOrder(new Ordering().addDescending(Plan._version));
PlanEntity previousPlan = planQuery.count() > 0 ? planQuery.collect().getFirst() : null;
if (previousPlan != null){
if (previousPlan.getStatus().equals(PlanStatus.Finalized)) previousPlan.setVersionStatus(PlanVersionStatus.Current);
PlanStatusEntity previousPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, previousPlan.getStatusId(), true);
if (previousPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{previousPlan.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (previousPlanStatusEntity.getInternalStatus() != null && previousPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) previousPlan.setVersionStatus(PlanVersionStatus.Current);
else previousPlan.setVersionStatus(PlanVersionStatus.NotFinalized);
this.entityManager.merge(previousPlan);
}
@ -1697,7 +1770,8 @@ public class PlanServiceImpl implements PlanService {
persist.setId(data.getId());
persist.setHash(data.getId().toString());
persist.setLabel(data.getLabel());
persist.setStatus(PlanStatus.Finalized);
PlanStatusEntity statusEntity = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.planstatus.PlanStatus._id));
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
persist.setDescription(data.getDescription());
persist.setBlueprint(data.getBlueprintId());
persist.setAccessType(data.getAccessType());
@ -2031,7 +2105,8 @@ public class PlanServiceImpl implements PlanService {
} else {
try {
this.entityManager.disableTenantFilters();
data = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public).first();
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
data = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();
@ -2065,7 +2140,8 @@ public class PlanServiceImpl implements PlanService {
PlanEntity data = null;
try {
this.entityManager.disableTenantFilters();
data = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public).first();
PlanStatusQuery statusQuery = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active);
data = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).isActive(IsActive.Active).planStatusSubQuery(statusQuery).accessTypes(PlanAccessType.Public).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();
@ -2088,6 +2164,7 @@ public class PlanServiceImpl implements PlanService {
xml.setTitle(data.getLabel());
xml.setLanguage(data.getLanguage());
xml.setAccess(data.getAccessType());
xml.setStatus(this.planStatusImportExportToExport(data.getStatusId()));
xml.setFinalizedAt(data.getFinalizedAt());
xml.setPublicAfter(data.getPublicAfter());
xml.setVersion(data.getVersion());
@ -2102,6 +2179,17 @@ public class PlanServiceImpl implements PlanService {
return xml;
}
private PlanStatusImportExport planStatusImportExportToExport(UUID statusId) throws InvalidApplicationException {
PlanStatusImportExport xml = new PlanStatusImportExport();
if (statusId == null) return xml;
PlanStatusEntity planStatusEntity = this.entityManager.find(PlanStatusEntity.class, statusId, true);
if (planStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{statusId, PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
xml.setId(planStatusEntity.getId());
xml.setName(planStatusEntity.getName());
return xml;
}
private List<DescriptionImportExport> descriptionsToExport(PlanEntity data, Boolean isPublic) throws JAXBException, InvalidApplicationException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException {
List<DescriptionEntity> descriptions;
if (!isPublic) {
@ -2299,7 +2387,6 @@ public class PlanServiceImpl implements PlanService {
PlanPersist persist = new PlanPersist();
persist.setLabel(label);
persist.setStatus(PlanStatus.Draft);
persist.setDescription(planXml.getDescription());
persist.setAccessType(planXml.getAccess());
persist.setLanguage(planXml.getLanguage());
@ -2601,7 +2688,6 @@ public class PlanServiceImpl implements PlanService {
PlanPersist persist = new PlanPersist();
persist.setLabel(planCommonModelConfig.getLabel());
persist.setStatus(PlanStatus.Draft);
persist.setDescription(model.getDescription());
switch (model.getAccessType()) {
case Public -> persist.setAccessType(PlanAccessType.Public);

View File

@ -10,10 +10,14 @@ import org.opencdmp.model.persist.planstatus.PlanStatusPersist;
import org.opencdmp.model.planstatus.PlanStatus;
import javax.management.InvalidApplicationException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public interface PlanStatusService {
PlanStatus persist(PlanStatusPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
Map<UUID, List<UUID>> getAuthorizedAvailableStatusIds(List<UUID> planIds);
}

View File

@ -3,6 +3,7 @@ package org.opencdmp.service.planstatus;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
@ -13,24 +14,36 @@ import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import jakarta.xml.bind.JAXBException;
import org.jetbrains.annotations.NotNull;
import org.opencdmp.authorization.AffiliatedResource;
import org.opencdmp.authorization.Permission;
import org.opencdmp.authorization.authorizationcontentresolver.AuthorizationContentResolver;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionAuthorizationEntity;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionAuthorizationItemEntity;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
import org.opencdmp.commons.types.planworkflow.PlanWorkflowDefinitionEntity;
import org.opencdmp.commons.types.planworkflow.PlanWorkflowDefinitionTransitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.PlanEntity;
import org.opencdmp.data.PlanStatusEntity;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.event.EventBroker;
import org.opencdmp.event.PlanStatusTouchedEvent;
import org.opencdmp.model.builder.planstatus.PlanStatusBuilder;
import org.opencdmp.model.deleter.PlanStatusDeleter;
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionAuthorizationItemPersist;
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionAuthorizationPersist;
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionPersist;
import org.opencdmp.model.persist.planstatus.PlanStatusPersist;
import org.opencdmp.model.plan.Plan;
import org.opencdmp.model.planstatus.PlanStatus;
import org.opencdmp.query.PlanQuery;
import org.opencdmp.query.PlanStatusQuery;
import org.opencdmp.service.custompolicy.CustomPolicyService;
import org.opencdmp.service.planworkflow.PlanWorkflowService;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
@ -38,8 +51,8 @@ import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class PlanStatusServiceImpl implements PlanStatusService {
@ -55,8 +68,14 @@ public class PlanStatusServiceImpl implements PlanStatusService {
private final TenantEntityManager entityManager;
private final MessageSource messageSource;
private final ErrorThesaurusProperties errors;
private final EventBroker eventBroker;
private final TenantScope tenantScope;
private final PlanWorkflowService planWorkflowService;
private final CustomPolicyService customPolicyService;
private final AuthorizationContentResolver authorizationContentResolver;
private final QueryFactory queryFactory;
public PlanStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authorizationService, ConventionService conventionService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors, EventBroker eventBroker) {
public PlanStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authorizationService, ConventionService conventionService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors, EventBroker eventBroker, TenantScope tenantScope, PlanWorkflowService planWorkflowService, CustomPolicyService customPolicyService, AuthorizationContentResolver authorizationContentResolver, QueryFactory queryFactory) {
this.builderFactory = builderFactory;
this.deleterFactory = deleterFactory;
@ -66,6 +85,12 @@ public class PlanStatusServiceImpl implements PlanStatusService {
this.entityManager = entityManager;
this.messageSource = messageSource;
this.errors = errors;
this.eventBroker = eventBroker;
this.tenantScope = tenantScope;
this.planWorkflowService = planWorkflowService;
this.customPolicyService = customPolicyService;
this.authorizationContentResolver = authorizationContentResolver;
this.queryFactory = queryFactory;
}
@Override
@ -90,6 +115,7 @@ public class PlanStatusServiceImpl implements PlanStatusService {
data.setName(model.getName());
data.setDescription(model.getDescription());
data.setAction(model.getAction());
data.setInternalStatus(model.getInternalStatus());
data.setDefinition(this.xmlHandlingService.toXml(this.buildPlanStatusDefinitionEntity(model.getDefinition())));
data.setUpdatedAt(Instant.now());
@ -101,6 +127,8 @@ public class PlanStatusServiceImpl implements PlanStatusService {
this.entityManager.flush();
this.eventBroker.emit(new PlanStatusTouchedEvent(data.getId(), this.tenantScope.getTenantCode()));
return this.builderFactory.builder(PlanStatusBuilder.class).build(BaseFieldSet.build(fields, PlanStatus._id), data);
}
@ -122,6 +150,8 @@ public class PlanStatusServiceImpl implements PlanStatusService {
PlanStatusDefinitionAuthorizationEntity definitionAuthorizationData = this.buildPlanStatusDefinitionAuthorizationEntity(persist.getAuthorization());
data.setAuthorization(definitionAuthorizationData);
}
if (!this.conventionService.isListNullOrEmpty(persist.getAvailableActions())) data.setAvailableActions(persist.getAvailableActions());
return data;
}
@ -149,4 +179,34 @@ public class PlanStatusServiceImpl implements PlanStatusService {
return data;
}
@Override
public Map<UUID, List<UUID>> getAuthorizedAvailableStatusIds(List<UUID> planIds) {
Map<UUID, List<UUID>> authorizedStatusMap = new HashMap<>();
PlanWorkflowDefinitionEntity definition;
try {
definition = this.planWorkflowService.getWorkFlowDefinition();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
List<PlanEntity> planEntities = this.queryFactory.query(PlanQuery.class).ids(planIds).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(Plan._id).ensure(Plan._status));
List<PlanStatusEntity> statusEntities = this.queryFactory.query(PlanStatusQuery.class).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(PlanStatus._id));
for (PlanEntity plan: planEntities) {
authorizedStatusMap.put(plan.getId(), new ArrayList<>());
AffiliatedResource affiliatedResource = this.authorizationContentResolver.planAffiliation(plan.getId());
for (PlanStatusEntity status: statusEntities) {
List<PlanWorkflowDefinitionTransitionEntity> availableTransitions = definition.getStatusTransitions().stream().filter(x -> x.getFromStatusId().equals(plan.getStatusId())).collect(Collectors.toList());
if (availableTransitions.stream().filter(x -> x.getToStatusId().equals(status.getId())).findFirst().orElse(null) != null) {
String editPermission = this.customPolicyService.getPlanStatusCanEditStatusPermission(status.getId());
Boolean isAllowed = affiliatedResource == null ? this.authorizationService.authorize(editPermission) : this.authorizationService.authorizeAtLeastOne(List.of(affiliatedResource), editPermission);
if (isAllowed) authorizedStatusMap.get(plan.getId()).add(status.getId());
}
}
}
return authorizedStatusMap;
}
}

View File

@ -6,6 +6,7 @@ import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.FieldSet;
import jakarta.xml.bind.JAXBException;
import org.opencdmp.commons.types.planworkflow.PlanWorkflowDefinitionEntity;
import org.opencdmp.model.persist.planworkflow.PlanWorkflowPersist;
import org.opencdmp.model.planworkflow.PlanWorkflow;
@ -16,4 +17,6 @@ public interface PlanWorkflowService {
PlanWorkflow persist(PlanWorkflowPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
PlanWorkflowDefinitionEntity getWorkFlowDefinition() throws InvalidApplicationException;
}

View File

@ -3,6 +3,7 @@ package org.opencdmp.service.planworkflow;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
@ -12,9 +13,11 @@ import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import jakarta.xml.bind.JAXBException;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.authorization.Permission;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.types.planworkflow.PlanWorkflowDefinitionEntity;
import org.opencdmp.commons.types.planworkflow.PlanWorkflowDefinitionTransitionEntity;
import org.opencdmp.convention.ConventionService;
@ -27,6 +30,7 @@ import org.opencdmp.model.persist.planworkflow.PlanWorkflowDefinitionPersist;
import org.opencdmp.model.persist.planworkflow.PlanWorkflowDefinitionTransitionPersist;
import org.opencdmp.model.persist.planworkflow.PlanWorkflowPersist;
import org.opencdmp.model.planworkflow.PlanWorkflow;
import org.opencdmp.query.PlanWorkflowQuery;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
@ -51,7 +55,10 @@ public class PlanWorkflowServiceImpl implements PlanWorkflowService {
private final DeleterFactory deleterFactory;
private final MessageSource messageSource;
private final ErrorThesaurusProperties errors;
public PlanWorkflowServiceImpl(AuthorizationService authorizationService, ConventionService conventionService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager, BuilderFactory builderFactory, DeleterFactory deleterFactory, MessageSource messageSource, ErrorThesaurusProperties errors) {
private final TenantScope tenantScope;
private final QueryFactory queryFactory;
public PlanWorkflowServiceImpl(AuthorizationService authorizationService, ConventionService conventionService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager, BuilderFactory builderFactory, DeleterFactory deleterFactory, MessageSource messageSource, ErrorThesaurusProperties errors, TenantScope tenantScope, QueryFactory queryFactory) {
this.authorizationService = authorizationService;
this.conventionService = conventionService;
this.xmlHandlingService = xmlHandlingService;
@ -60,6 +67,8 @@ public class PlanWorkflowServiceImpl implements PlanWorkflowService {
this.deleterFactory = deleterFactory;
this.messageSource = messageSource;
this.errors = errors;
this.tenantScope = tenantScope;
this.queryFactory = queryFactory;
}
@Override
@ -136,4 +145,36 @@ public class PlanWorkflowServiceImpl implements PlanWorkflowService {
return data;
}
@Override
public PlanWorkflowDefinitionEntity getWorkFlowDefinition() throws InvalidApplicationException {
PlanWorkflowQuery query = this.queryFactory.query(PlanWorkflowQuery.class).authorize(AuthorizationFlags.AllExceptPublic).isActives(IsActive.Active);
if (this.tenantScope.isDefaultTenant()) query = query.defaultTenant(true);
List<PlanWorkflowEntity> planWorkflowEntities = query.collect();
if (this.conventionService.isListNullOrEmpty(planWorkflowEntities)) throw new MyApplicationException("Plan workflows not found!");
PlanWorkflowEntity entity = null;
if (!this.tenantScope.isDefaultTenant()) {
entity = planWorkflowEntities.stream().filter(x -> {
try {
return (this.tenantScope.getTenant().equals(x.getTenantId()));
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
}).findFirst().orElse(null);
}
// fallback to default tenant
if (entity == null) {
entity = planWorkflowEntities.stream().filter(x -> x.getTenantId() == null).findFirst().orElse(null);
}
if (entity == null) throw new MyApplicationException("Plan workflow not found!");
PlanWorkflowDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(PlanWorkflowDefinitionEntity.class, entity.getDefinition());
if (definition == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{entity.getId(), PlanWorkflowDefinitionEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
return definition;
}
}

View File

@ -128,6 +128,11 @@
<artifactId>exceptions-web</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>oidc-authz</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
<build>

View File

@ -44,6 +44,7 @@ public class AffiliatedAuthorizationHandler extends AuthorizationHandler<Affilia
CustomPermissionAttributesProperties.MyPermission policy = this.myConfiguration.getMyPolicies().get(permission);
boolean hasPlanPermission = policy != null && this.hasPermission(policy.getPlan(), planUserRoles);
boolean hasDescriptionTemplatePermission = policy != null && this.hasPermission(policy.getDescriptionTemplate(), userDescriptionTemplateRoles);
if (hasPlanPermission || hasDescriptionTemplatePermission) hits += 1;
}
if ((req.getMatchAll() && req.getRequiredPermissions().size() == hits) || (!req.getMatchAll() && hits > 0))

View File

@ -1,24 +1,94 @@
package org.opencdmp.authorization;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
import org.opencdmp.event.DescriptionStatusTouchedEvent;
import org.opencdmp.event.PlanStatusTouchedEvent;
import org.opencdmp.service.custompolicy.CustomPolicyCacheService;
import org.opencdmp.service.custompolicy.CustomPolicyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
@Configuration
@EnableConfigurationProperties(CustomPermissionAttributesProperties.class)
public class CustomPermissionAttributesConfiguration {
private final CustomPermissionAttributesProperties properties;
private HashMap<String, CustomPermissionAttributesProperties.MyPermission> myPolicies;
private final CustomPolicyService customPolicyService;
private final CustomPolicyCacheService customPolicyCacheService;
@Autowired
public CustomPermissionAttributesConfiguration(CustomPermissionAttributesProperties properties) {
public CustomPermissionAttributesConfiguration(CustomPermissionAttributesProperties properties, CustomPolicyService customPolicyService, CustomPolicyCacheService customPolicyCacheService) {
this.properties = properties;
this.customPolicyService = customPolicyService;
this.customPolicyCacheService = customPolicyCacheService;
}
@EventListener
public void handlePlanTouchedEvent(PlanStatusTouchedEvent event) {
this.customPolicyCacheService.clearCache(event);
this.refresh(true);
}
@EventListener
public void handleDescriptionStatusTouchedEvent(DescriptionStatusTouchedEvent event) {
this.customPolicyCacheService.clearCache(event);
this.refresh(true);
}
public HashMap<String, CustomPermissionAttributesProperties.MyPermission> getMyPolicies() {
if (this.myPolicies == null) this.refresh(false);
return properties.getPolicies();
}
public void refresh(boolean force) {
if (!force && this.myPolicies != null) return;
this.myPolicies = this.properties.getPolicies();
this.myPolicies.putAll(this.buildAffiliatedCustomPermissions());
}
private HashMap<String, CustomPermissionAttributesProperties.MyPermission> buildAffiliatedCustomPermissions() {
HashMap<String, CustomPermissionAttributesProperties.MyPermission> affiliatedCustomPermissions = new HashMap<>();
this.buildAffiliatedPlanCustomPermissions(affiliatedCustomPermissions);
this.buildAffiliatedDescriptionCustomPermissions(affiliatedCustomPermissions);
return affiliatedCustomPermissions;
}
private void buildAffiliatedPlanCustomPermissions(HashMap<String, CustomPermissionAttributesProperties.MyPermission> affiliatedCustomPermissions) {
Map<UUID, PlanStatusDefinitionEntity> map = this.customPolicyService.buildPlanStatusDefinitionMap();
if (map == null) return;
for (UUID statusId: map.keySet()) {
PlanStatusDefinitionEntity definition = map.get(statusId);
if (definition != null && definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null) {
CustomPermissionAttributesProperties.MyPermission myPermission = new CustomPermissionAttributesProperties.MyPermission(new PlanRole(new HashSet<>(definition.getAuthorization().getEdit().getPlanRoles())), null);
affiliatedCustomPermissions.put(this.customPolicyService.getPlanStatusCanEditStatusPermission(statusId), myPermission);
}
}
}
private void buildAffiliatedDescriptionCustomPermissions(HashMap<String, CustomPermissionAttributesProperties.MyPermission> affiliatedCustomPermissions) {
Map<UUID, DescriptionStatusDefinitionEntity> map = this.customPolicyService.buildDescriptionStatusDefinitionMap();
if (map == null) return;
for (UUID statusId: map.keySet()) {
DescriptionStatusDefinitionEntity definition = map.get(statusId);
if (definition != null && definition.getAuthorization() != null && definition.getAuthorization().getEdit() != null) {
CustomPermissionAttributesProperties.MyPermission myPermission = new CustomPermissionAttributesProperties.MyPermission(new PlanRole(new HashSet<>(definition.getAuthorization().getEdit().getPlanRoles())), null);
affiliatedCustomPermissions.put(this.customPolicyService.getDescriptionStatusCanEditStatusPermission(statusId), myPermission);
}
}
}
}

View File

@ -0,0 +1,50 @@
package org.opencdmp.configurations;
import gr.cite.commons.web.authz.configuration.AuthorizationConfiguration;
import gr.cite.commons.web.authz.configuration.PermissionPolicyContextImpl;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.event.DescriptionStatusTouchedEvent;
import org.opencdmp.event.PlanStatusTouchedEvent;
import org.opencdmp.service.custompolicy.CustomPolicyCacheService;
import org.opencdmp.service.custompolicy.CustomPolicyService;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class OpencdmpPermissionPolicyContextImpl extends PermissionPolicyContextImpl {
private final CustomPolicyService customPolicyService;
private final CustomPolicyCacheService customPolicyCacheService;
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(OpencdmpPermissionPolicyContextImpl.class));
public OpencdmpPermissionPolicyContextImpl(AuthorizationConfiguration authorizationConfiguration, CustomPolicyService customPolicyService, CustomPolicyCacheService customPolicyCacheService) {
super(authorizationConfiguration);
this.customPolicyService = customPolicyService;
this.customPolicyCacheService = customPolicyCacheService;
}
@EventListener
public void handlePlanTouchedEvent(PlanStatusTouchedEvent event) {
this.customPolicyCacheService.clearCache(event);
this.refresh(true);
}
@EventListener
public void handleDescriptionStatusTouchedEvent(DescriptionStatusTouchedEvent event) {
this.customPolicyCacheService.clearCache(event);
this.refresh(true);
}
@Override
public void refresh(boolean force) {
if (!force && this.policies != null) return;
this.policies = this.authorizationConfiguration.getRawPolicies();
this.extendedClaims = this.authorizationConfiguration.getRawExtendedClaims();
this.policies.putAll(this.customPolicyService.buildPlanStatusPolicies());
this.policies.putAll(this.customPolicyService.buildDescriptionStatusPolicies());
logger.info("Authorization policies found: {}", this.policies.size());
this.reload();
}
}

View File

@ -3,7 +3,6 @@ package org.opencdmp.configurations;
import org.opencdmp.authorization.*;
import gr.cite.commons.web.authz.handler.AuthorizationHandler;
import gr.cite.commons.web.authz.handler.PermissionClientAuthorizationHandler;
import gr.cite.commons.web.authz.policy.AuthorizationRequirement;
import gr.cite.commons.web.authz.policy.AuthorizationRequirementMapper;
import gr.cite.commons.web.authz.policy.AuthorizationResource;
@ -26,9 +25,7 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen
import jakarta.servlet.Filter;
import jakarta.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.*;
@Configuration
@EnableWebSecurity
@ -107,6 +104,11 @@ public class SecurityConfiguration {
};
}
// @Bean()
// public PermissionPolicyContext permissionPolicyContext(){
// return new PermissionPolicyContextImpl(configuration);
// }
@Bean
AuthorizationRequirementMapper authorizationRequirementMapper() {
return new AuthorizationRequirementMapper() {
@ -148,3 +150,4 @@ public class SecurityConfiguration {
return endpoint;
}
}

Some files were not shown because too many files have changed in this diff Show More