ActivityFlowLink.java
/*
* The coLAB project
* Copyright (C) 2021-2023 AlbaSim, MEI, HEIG-VD, HES-SO
*
* Licensed under the MIT License
*/
package ch.colabproject.colab.api.model.link;
import ch.colabproject.colab.api.exceptions.ColabMergeException;
import ch.colabproject.colab.api.model.ColabEntity;
import ch.colabproject.colab.api.model.WithWebsocketChannels;
import ch.colabproject.colab.api.model.card.Card;
import ch.colabproject.colab.api.model.common.DeletionStatus;
import ch.colabproject.colab.api.model.common.Tracking;
import ch.colabproject.colab.api.model.tools.EntityHelper;
import ch.colabproject.colab.api.security.permissions.Conditions;
import ch.colabproject.colab.api.ws.channel.tool.ChannelsBuilders.ChannelsBuilder;
import ch.colabproject.colab.api.ws.channel.tool.ChannelsBuilders.EmptyChannelBuilder;
import javax.json.bind.annotation.JsonbTransient;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
/**
* Link to show that a card must be handled before another one.
*
* @author sandra
*/
@Entity
@Table(
indexes = {
@Index(columnList = "nextcard_id"),
@Index(columnList = "previouscard_id"), }
)
public class ActivityFlowLink implements ColabEntity, WithWebsocketChannels {
private static final long serialVersionUID = 1L;
/** Link sequence name */
public static final String LINK_SEQUENCE_NAME = "link_seq";
// ---------------------------------------------------------------------------------------------
// fields
// ---------------------------------------------------------------------------------------------
/**
* Link ID
*/
@Id
@SequenceGenerator(name = LINK_SEQUENCE_NAME, allocationSize = 20)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = LINK_SEQUENCE_NAME)
private Long id;
/**
* creation + modification + erasure tracking data
*/
@Embedded
private Tracking trackingData;
/**
* Is it in a bin or ready to be definitely deleted. Null means active.
*/
@Enumerated(EnumType.STRING)
private DeletionStatus deletionStatus;
/**
* The card to handle before
*/
@ManyToOne(fetch = FetchType.LAZY)
@NotNull
@JsonbTransient
private Card previousCard;
/**
* The ID of the card to handle before (serialization sugar)
*/
@Transient
private Long previousCardId;
/**
* The card to handle after
*/
@ManyToOne(fetch = FetchType.LAZY)
@NotNull
@JsonbTransient
private Card nextCard;
/**
* The ID of the card to handle after (serialization sugar)
*/
@Transient
private Long nextCardId;
// ---------------------------------------------------------------------------------------------
// getters and setters
// ---------------------------------------------------------------------------------------------
/**
* @return the link id
*/
@Override
public Long getId() {
return id;
}
/**
* @param id the link id
*/
public void setId(Long id) {
this.id = id;
}
/**
* Get the tracking data
*
* @return tracking data
*/
@Override
public Tracking getTrackingData() {
return trackingData;
}
/**
* Set tracking data
*
* @param trackingData new tracking data
*/
@Override
public void setTrackingData(Tracking trackingData) {
this.trackingData = trackingData;
}
@Override
public DeletionStatus getDeletionStatus() {
return deletionStatus;
}
@Override
public void setDeletionStatus(DeletionStatus status) {
this.deletionStatus = status;
}
/**
* @return the card to handle before
*/
public Card getPreviousCard() {
return previousCard;
}
/**
* @param previousCard the card to handle before
*/
public void setPreviousCard(Card previousCard) {
this.previousCard = previousCard;
}
/**
* get the id of the card to handle before. To be sent to client
*
* @return the id of the card to handle before
*/
public Long getPreviousCardId() {
if (this.previousCard != null) {
return this.previousCard.getId();
} else {
return previousCardId;
}
}
/**
* set the id of the card to handle before. For serialization only
*
* @param previousCardId the id of the card to handle before
*/
public void setPreviousCardId(Long previousCardId) {
this.previousCardId = previousCardId;
}
/**
* @return the card to handle after
*/
public Card getNextCard() {
return nextCard;
}
/**
* @param nextCard the card to handle after
*/
public void setNextCard(Card nextCard) {
this.nextCard = nextCard;
}
/**
* get the id of the card to handle after. To be sent to client
*
* @return the id of the card to handle after
*/
public Long getNextCardId() {
if (this.nextCard != null) {
return this.nextCard.getId();
} else {
return nextCardId;
}
}
/**
* set the id of the card to handle after. For serialization only
*
* @param nextCardId the id of the card to handle after
*/
public void setNextCardId(Long nextCardId) {
this.nextCardId = nextCardId;
}
// ---------------------------------------------------------------------------------------------
// concerning the whole class
// ---------------------------------------------------------------------------------------------
@Override
public void mergeToUpdate(ColabEntity other) throws ColabMergeException {
if (other instanceof ActivityFlowLink) {
ActivityFlowLink o = (ActivityFlowLink) other;
this.setDeletionStatus(o.getDeletionStatus());
} else {
throw new ColabMergeException(this, other);
}
}
@Override
public ChannelsBuilder getChannelsBuilder() {
if (this.nextCard != null) {
return this.nextCard.getChannelsBuilder();
} else {
// such an orphan shouldn't exist...
return new EmptyChannelBuilder();
}
}
@Override
@JsonbTransient
public Conditions.Condition getReadCondition() {
return new Conditions.Or(
new Conditions.HasCardReadRight(this.previousCard),
new Conditions.HasCardReadRight(this.nextCard)
);
}
// TODO what is best : And / Or ?
@Override
@JsonbTransient
public Conditions.Condition getUpdateCondition() {
return new Conditions.Or(
this.previousCard.getUpdateCondition(),
this.nextCard.getUpdateCondition()
);
}
@Override
public int hashCode() {
return EntityHelper.hashCode(this);
}
@Override
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
public boolean equals(Object obj) {
return EntityHelper.equals(this, obj);
}
@Override
public String toString() {
return "ActivityFlowLink{" + "id=" + id + ", deletion=" + getDeletionStatus()
+ ", previousCardId=" + previousCardId + ", nextCardId=" + nextCardId + "}";
}
}