/** * Copyright (c) 2009 - 2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.model; import org.candlepin.common.jackson.HateoasInclude; import com.fasterxml.jackson.annotation.JsonFilter; import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Index; import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Transient; import javax.validation.constraints.NotNull; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; /** * Entitlements are documents either signed XML or other certificate which * control what a particular Consumer can use. There are a number of types * of Entitlements: * * 1. Quantity Limited (physical & virtual) * 2. Version Limited * 3. Hardware Limited (i.e # of sockets, # of cores, etc) * 4. Functional Limited (i.e. Update, Management, Provisioning, etc) * 5. Site License * 6. Floating License * 7. Value-Based or "Metered" (i.e. per unit of time, per hardware * consumption, etc) * 8. Draw-Down (i.e. 100 hours or training classes to be consumed over * some period of time or limited number of support calls) */ @XmlRootElement @XmlAccessorType(XmlAccessType.PROPERTY) @Entity @Table(name = Entitlement.DB_TABLE) @JsonFilter("EntitlementFilter") public class Entitlement extends AbstractHibernateObject implements Linkable, Owned, Named, ConsumerProperty, Comparable<Entitlement>, Eventful { /** Name of the table backing this object in the database */ public static final String DB_TABLE = "cp_entitlement"; private static final long serialVersionUID = 1L; @Id @GeneratedValue(generator = "system-uuid") @GenericGenerator(name = "system-uuid", strategy = "uuid") @Column(length = 32) @NotNull private String id; @ManyToOne @ForeignKey(name = "fk_entitlement_owner") @JoinColumn(nullable = false) @Index(name = "cp_entitlement_owner_fk_idx") @NotNull private Owner owner; @ManyToOne @ForeignKey(name = "fk_entitlement_consumer") @JoinColumn(nullable = false) @Index(name = "cp_entitlement_consumer_fk_idx") @NotNull private Consumer consumer; @ManyToOne @ForeignKey(name = "fk_entitlement_pool") @JoinColumn(nullable = true) @Index(name = "cp_entitlement_pool_fk_idx") @NotNull private Pool pool; // Not positive this should be mapped here, not all entitlements will have // certificates. @OneToMany(mappedBy = "entitlement", cascade = CascadeType.ALL) @BatchSize(size = 100) private Set<EntitlementCertificate> certificates = new HashSet<EntitlementCertificate>(); private Integer quantity; private boolean dirty = false; // If the entitlement is created before it becomes active, we need to // rerun compliance once we hit the active date range. private boolean updatedOnStart = false; private Date endDateOverride; // We don't want to send entitlement delete events when the pool is // entirely deleted @Transient private boolean deletedFromPool; /** * default ctor */ public Entitlement() { } /** * @return the id */ @Override @HateoasInclude public String getId() { return id; } /** * @param id the id to set */ public void setId(String id) { this.id = id; } /** * ctor * @param poolIn pool associated with the entitlement * @param consumerIn consumer associated with the entitlement */ public Entitlement(Pool poolIn, Consumer consumerIn, Integer quantityIn) { pool = poolIn; owner = consumerIn.getOwner(); consumer = consumerIn; quantity = quantityIn == null || quantityIn.intValue() < 1 ? 1 : quantityIn; updatedOnStart = poolIn.getStartDate().after(new Date()); deletedFromPool = false; } /** * @return the owner */ @XmlTransient public Owner getOwner() { return owner; } /** * @param ownerIn the owner to set */ public void setOwner(Owner ownerIn) { this.owner = ownerIn; } /** * @return Returns the pool. */ public Pool getPool() { return pool; } /** * @param poolIn The pool to set. */ public void setPool(Pool poolIn) { pool = poolIn; } /** * @return Returns the startDate. */ public Date getStartDate() { if (pool == null) { return null; } return pool.getStartDate(); } public void setStartDate(Date date) { // Only for serialization, start date lives on pool now. } /** * @return Returns the endDate. If an override is specified for this entitlement, * we return this value. If not we'll use the end date of the pool. */ public Date getEndDate() { if (endDateOverride != null) { return endDateOverride; } if (pool == null) { return null; } return pool.getEndDate(); } public void setEndDate(Date date) { // Only for serialization, end date lives on pool now. } /** * An optional end date override for this entitlement. * * Typically this is set to null, and the pool's end date is used. In some cases * we need to control the expiry of an entitlement separate from the pool. * * @return optional end date override for this entitlement. */ @XmlTransient public Date getEndDateOverride() { return endDateOverride; } public void setEndDateOverride(Date endDateOverride) { this.endDateOverride = endDateOverride; } /** * @return return the associated Consumer */ public Consumer getConsumer() { return consumer; } /** * associates the given consumer with this entitlement. * @param consumer consumer to associate. */ public void setConsumer(Consumer consumer) { this.consumer = consumer; } public Integer getQuantity() { return quantity; } public void setQuantity(Integer quantity) { this.quantity = quantity; } public Set<EntitlementCertificate> getCertificates() { return certificates; } public void setCertificates(Set<EntitlementCertificate> certificates) { this.certificates.clear(); if (certificates != null) { this.certificates.addAll(certificates); } } public void addCertificate(EntitlementCertificate certificate) { certificate.setEntitlement(this); certificates.add(certificate); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Entitlement[id=").append(id); if (pool != null) { sb.append(", product=").append(pool.getProductId()); sb.append(", pool=").append(pool.getId()); } if (consumer != null) { sb.append(", consumer=").append(consumer.getUuid()); } sb.append("]"); return sb.toString(); } @HateoasInclude public String getHref() { return "/entitlements/" + getId(); } public void setHref(String href) { /* * No-op, here to aid with updating objects which have nested objects that were * originally sent down to the client in HATEOAS form. */ } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Entitlement)) { return false; } Entitlement e = (Entitlement) obj; return (id == null ? e.id == null : id.equals(e.getId())); } @Override public int hashCode() { int result = 17; if (null != id) { result = 37 * result + id.hashCode(); } return result; } @XmlTransient public boolean isDirty() { return dirty; } public void setDirty(boolean dirty) { this.dirty = dirty; } @XmlTransient public boolean isValidOnDate(Date d) { return (d.after(this.getStartDate()) || d.equals(this.getStartDate())) && (d.before(this.getEndDate()) || d.equals(this.getEndDate())); } @XmlTransient public boolean isValid() { return this.isValidOnDate(new Date()); } @Override public int compareTo(Entitlement other) { int compare = this.getPool().compareTo(other.getPool()); if (compare == 0) { return (this.getId() == null ^ other.getId() == null) ? (this.getId() == null ? -1 : 1) : this.getId() == other.getId() ? 0 : this.getId().compareTo(other.getId()); } return compare; } @Override @XmlTransient public String getName() { if (pool != null) { return pool.getProductName(); } return null; } @XmlTransient public boolean isUpdatedOnStart() { return updatedOnStart; } public void setUpdatedOnStart(boolean updatedOnStart) { this.updatedOnStart = updatedOnStart; } @XmlTransient public boolean deletedFromPool() { return deletedFromPool; } public void setDeletedFromPool(boolean deletedFromPool) { this.deletedFromPool = deletedFromPool; } }