/* * Copyright @ 2013 CurisTEC, S.A.S. All Rights Reserved. */ package net.curisit.securis.db; import java.io.Serializable; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.NamedQueries; import jakarta.persistence.NamedQuery; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import org.hibernate.annotations.Type; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import net.curisit.integrity.commons.Utils; /** * Pack *
* Group/bundle of licenses for an organization and application (via LicenseType).
* Tracks capacity, availability, status, and validity windows.
*
* Mapping details:
* - Table: pack
* - ManyToOne to Organization, LicenseType, User (createdBy)
* - OneToMany licenses (lazy)
* - Custom type: net.curisit.securis.db.common.PackStatusType
* - Named queries for listing and filtering by org/app.
*
* @author JRA
* Last reviewed by JRA on Oct 5, 2025.
*/
@JsonAutoDetect
@JsonInclude(Include.NON_NULL)
@Entity
@Table(name = "pack")
@JsonIgnoreProperties(ignoreUnknown = true)
@NamedQueries({
@NamedQuery(name = "list-packs", query = "SELECT pa FROM Pack pa"),
@NamedQuery(name = "pack-by-code", query = "SELECT pa FROM Pack pa where pa.code = :code"),
@NamedQuery(name = "list-packs-by-lic-type", query = "SELECT pa FROM Pack pa where pa.licenseType.id = :lt_id"),
@NamedQuery(name = "list-packs-by-orgs-apps", query = "SELECT pa FROM Pack pa where pa.organization.id in :list_ids_org and pa.licenseType.application.id in :list_ids_app "),
@NamedQuery(name = "list-packs-by-apps", query = "SELECT pa FROM Pack pa where pa.licenseType.application.id in :list_ids_app ")
})
public class Pack implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Integer id;
private String code;
private String comments;
private Boolean frozen;
@Column(name = "creation_timestamp")
@JsonProperty("creation_timestamp")
private Date creationTimestamp;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "organization_id")
private Organization organization;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "license_type_id")
private LicenseType licenseType;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "created_by")
private User createdBy;
@JsonIgnore
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH }, mappedBy = "pack")
private Set
* Return primary key.
*
* @return id
*/
public Integer getId() { return id; }
/**
* setId
* Set primary key.
*
* @param id
*/
public void setId(Integer id) { this.id = id; }
/**
* getCode
* Return pack code.
*
* @return packCode
*/
public String getCode() { return code; }
/**
* setCode
* Set pack code.
*
* @param packCode
*/
public void setCode(String code) { this.code = code; }
/**
* getCreationTimestamp
* Return creation timestamp.
*
* @return creationTimestamp
*/
public Date getCreationTimestamp() { return creationTimestamp; }
/**
* setCreationTimestamp
* Set creation timestamp.
*
* @param creationTimestamp
*/
public void setCreationTimestamp(Date creationTimestamp) { this.creationTimestamp = creationTimestamp; }
/**
* getOrganization
* Return owning organization (entity).
*
* @return organization
*/
public Organization getOrganization() { return organization; }
/**
* setOrganization
* Set owning organization (entity).
*
* @param organization
*/
public void setOrganization(Organization organization) { this.organization = organization; }
/**
* getLicenseType
* Return license type (entity).
*
* @return licenseType
*/
public LicenseType getLicenseType() { return licenseType; }
/**
* setLicenseType
* Set license type (entity).
*
* @param licenseType
*/
public void setLicenseType(LicenseType licenseType) { this.licenseType = licenseType; }
/**
* getCreatedBy
* Return creator (entity).
*
* @return user
*/
public User getCreatedBy() { return createdBy; }
/**
* setCreatedBy
* Set creator (entity).
*
* @param user
*/
public void setCreatedBy(User createdBy) { this.createdBy = createdBy; }
/**
* getNumLicenses
* Return capacity (licenses).
*
* @return numLicenses
* Number of licenses
*/
public int getNumLicenses() { return numLicenses; }
/**
* setNumLicenses
* Set capacity (licenses).
*
* @param numLicenses
* Number of licenses
*/
public void setNumLicenses(int numLicenses) { this.numLicenses = numLicenses; }
/**
* getNumActivations
* Count ACTIVE/PRE_ACTIVE licenses in this pack.
*
* @return numActivations
* number of activated licenses
*/
@JsonProperty("num_activations")
public int getNumActivations() {
if (licenses == null) return 0;
int num = 0;
for (License lic : licenses) {
if (lic.getStatus() == LicenseStatus.ACTIVE || lic.getStatus() == LicenseStatus.PRE_ACTIVE) num++;
}
return num;
}
/**
* getNumCreations
* Count all created licenses (including waiting for activation). Ignores CANCELLED.
*
* @return numCreations
* number of created licenses
*/
@JsonProperty("num_creations")
public int getNumCreations() {
if (licenses == null) return 0;
int num = 0;
for (License lic : licenses) {
if (lic.getStatus() != LicenseStatus.CANCELLED) num++;
}
return num;
}
/**
* getNumAvailables
* Number of available licenses in this pack: capacity - activations.
*
* @return numAvailable
* Number of available licenses
*/
@JsonProperty("num_available")
public int getNumAvailables() { return numLicenses - getNumActivations(); }
/**
* getOrgName
* Expose organization name.
*
* @return orgName
*/
@JsonProperty("organization_name")
public String getOrgName() { return organization == null ? null : organization.getName(); }
/**
* getAppName
* Expose application name via license type.
*
* @return appName
*/
@JsonProperty("application_name")
public String getAppName() {
if (licenseType == null) return null;
Application app = licenseType.getApplication();
return app == null ? null : app.getName();
}
/**
* getOrgId
* Expose organization id.
*
* @return orgId
*/
@JsonProperty("organization_id")
public Integer getOrgId() { return organization == null ? null : organization.getId(); }
/**
* setOrgId
* Setter by id for JSON binding (creates shallow Organization).
*
* @param orgId
*/
@JsonProperty("organization_id")
public void setOrgId(Integer idOrg) {
if (idOrg == null) {
organization = null;
} else {
organization = new Organization();
organization.setId(idOrg);
}
}
/**
* setLicTypeId
* Setter by id for JSON binding (creates shallow LicenseType).
*
* @param licTypeId
*/
@JsonProperty("license_type_id")
public void setLicTypeId(Integer idLT) {
if (idLT == null) {
licenseType = null;
} else {
licenseType = new LicenseType();
licenseType.setId(idLT);
}
}
/**
* getLicTypeId
* Expose license type id.
*
* @return licTypeId
*/
@JsonProperty("license_type_id")
public Integer getLicTypeId() { return licenseType == null ? null : licenseType.getId(); }
/**
* getCreatedById
* Expose creator username.
*
* @return username
*/
@JsonProperty("created_by_id")
public String getCreatedById() { return createdBy == null ? null : createdBy.getUsername(); }
/**
* setCreatedById
* Setter by username (creates shallow User).
*
* @param username
*/
@JsonProperty("created_by_id")
public void setCreatedById(String username) {
createdBy = new User();
createdBy.setUsername(username);
}
/**
* getCreatedByname
* Expose creator full display name.
*
* @return userName
*/
@JsonProperty("created_by_name")
public String getCreatedByname() {
return createdBy == null ? null
: String.format("%s %s (%s)", createdBy.getFirstName(),
createdBy.getLastName() != null ? createdBy.getLastName() : "",
createdBy.getUsername());
}
/**
* getLicenseTypeCode
* Expose license type code.
*
* @return licenseTypeCode
*/
@JsonProperty("licensetype_code")
public String getLicenseTypeCode() { return licenseType == null ? null : licenseType.getCode(); }
/**
* getComments
* Return comments.
*
* @return comments
*/
public String getComments() { return comments; }
/**
* setComments
* Set comments.
*
* @param comments
*/
public void setComments(String comments) { this.comments = comments; }
/**
* isLicensePreactivation
* Whether licenses are pre-activated.
*
* @return isLicensePreactivation
*/
public boolean isLicensePreactivation() { return licensePreactivation; }
/**
* setLicensePreactivation
* Set pre-activation flag.
*
* @param licensePreactivation
*/
public void setLicensePreactivation(boolean licensePreactivation) { this.licensePreactivation = licensePreactivation; }
/**
* getMetadata
* Return pack metadata entries.
*
* @return metadata
*/
public Set
* Set pack metadata entries.
*
* @param metadata
*/
public void setMetadata(Set
* Return pack status.
*
* @return packStatus
*/
public PackStatus getStatus() { return status; }
/**
* setStatus
* Set pack status.
*
* @param packStatus
*/
public void setStatus(PackStatus status) { this.status = status; }
/**
* getInitValidDate
* Return start of validity window.
*
* @return initValidDate
*/
public Date getInitValidDate() { return initValidDate; }
/**
* setInitValidDate
* Set start of validity window.
*
* @param initValidDate
*/
public void setInitValidDate(Date initValidDate) { this.initValidDate = initValidDate; }
/**
* getEndValidDate
* Return end of validity window.
*
* @return endValidDate
*/
public Date getEndValidDate() { return endValidDate; }
/**
* setEndValidDate
* Set end of validity window.
*
* @param endValidDate
*/
public void setEndValidDate(Date endValidDate) { this.endValidDate = endValidDate; }
/**
* getLicenses
* Return contained licenses (entity set).
*
* @return licenses
*/
public Set
* Set contained licenses (entity set).
*
* @param licenses
*/
public void setLicenses(Set
* Return preactivation validity (days).
*
* @return preactivationValidPeriod
*/
public Integer getPreactivationValidPeriod() { return preactivationValidPeriod; }
/**
* setPreactivationValidPeriod
* Set preactivation validity (days).
*
* @param preactivationValidPeriod
*/
public void setPreactivationValidPeriod(Integer preactivationValidPeriod) { this.preactivationValidPeriod = preactivationValidPeriod; }
/**
* getRenewValidPeriod
* Return renewal validity (days).
*
* @return renewValidPeriod
*/
public Integer getRenewValidPeriod() { return renewValidPeriod; }
/**
* setRenewValidPeriod
* Set renewal validity (days).
*
* @param renewValidPeriod
*/
public void setRenewValidPeriod(Integer renewValidPeriod) { this.renewValidPeriod = renewValidPeriod; }
// ---------------- Object methods ----------------
/**
* equals
* Compare the current object with the given object
*
* @param object
* @return isEquals
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Application)) return false;
return id != null && id.equals(Pack.class.cast(obj).id);
}
/**
* hashCode
* Get the object hashCode
*
* @return hashCode
*/
@Override
public int hashCode() { return (id == null ? 0 : id.hashCode()); }
/**
* toString
* Get the string describing the current object
*
* @return object string
*/
@Override
public String toString() { return String.format("Pack: ID: %d, code: %s", id, code); }
/**
* isFrozen
* Null-safe boolean getter.
*
* @return isFrozen
*/
public boolean isFrozen() { return frozen != null && frozen; }
/**
* setFrozen
* Set frozen flag (nullable wrapper).
*
* @param frozen
*/
public void setFrozen(Boolean frozen) { this.frozen = frozen; }
// ---------------- Status transitions ----------------
/**
* Action
* Available actions for the Pack
*/
public static class Action {
public static final int CREATE = 1;
public static final int ACTIVATION = 2;
public static final int PUT_ONHOLD = 3;
public static final int CANCEL = 4;
public static final int DELETE = 5;
}
/**
* Status
* Pack status
*/
public static class Status {
private static final Map
* Validate whether an action is allowed given the current pack status.
*
* @param action action constant
* @param currentStatus current pack status
* @return true if allowed
*/
public static boolean isActionValid(Integer action, PackStatus currentStatus) {
List