/**
* 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 com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import org.hibernate.Criteria;
import org.hibernate.ReplicationMode;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
import org.hibernate.sql.JoinType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* OwnerCurator
*/
public class OwnerCurator extends AbstractHibernateCurator<Owner> {
@Inject private CandlepinQueryFactory cpQueryFactory;
private static Logger log = LoggerFactory.getLogger(OwnerCurator.class);
public OwnerCurator() {
super(Owner.class);
}
@Transactional
public Owner replicate(Owner owner) {
this.currentSession().replicate(owner, ReplicationMode.EXCEPTION);
return owner;
}
@Transactional
@Override
public Owner create(Owner entity) {
return super.create(entity);
}
/**
* @param key owner's unique key to lookup.
* @return the owner whose key matches the one given.
*/
@Transactional
public Owner lookupByKey(String key) {
return (Owner) createSecureCriteria()
.add(Restrictions.eq("key", key))
.uniqueResult();
}
@Transactional
public CandlepinQuery<Owner> lookupByKeys(Collection<String> keys) {
DetachedCriteria criteria = this.createSecureDetachedCriteria()
.add(CPRestrictions.in("key", keys));
return this.cpQueryFactory.<Owner>buildQuery(this.currentSession(), criteria);
}
public Owner lookupWithUpstreamUuid(String upstreamUuid) {
return (Owner) createSecureCriteria()
.createCriteria("upstreamConsumer")
.add(Restrictions.eq("uuid", upstreamUuid))
.uniqueResult();
}
/**
* Note that this query looks up only provided products.
* @param productIds
* @return a list of owners
*/
public CandlepinQuery<Owner> lookupOwnersByActiveProduct(Collection<String> productIds) {
// NOTE: only used by superadmin API calls, no permissions filtering needed here.
DetachedCriteria poolIdQuery = DetachedCriteria.forClass(Pool.class, "pool")
.createAlias("pool.providedProducts", "providedProducts")
.add(CPRestrictions.in("providedProducts.id", productIds))
.setProjection(Property.forName("pool.id"));
DetachedCriteria ownerIdQuery = DetachedCriteria.forClass(Entitlement.class, "e")
.add(Subqueries.propertyIn("e.pool.id", poolIdQuery))
.createCriteria("pool").add(Restrictions.gt("endDate", new Date()))
.setProjection(Property.forName("e.owner.id"));
DetachedCriteria distinctQuery = DetachedCriteria.forClass(Owner.class, "o2")
.add(Subqueries.propertyIn("o2.id", ownerIdQuery))
.setProjection(Projections.distinct(Projections.property("o2.key")));
DetachedCriteria criteria = DetachedCriteria.forClass(Owner.class, "o")
.add(Subqueries.propertyIn("o.key", distinctQuery));
return this.cpQueryFactory.<Owner>buildQuery(this.currentSession(), criteria);
}
/**
* Retrieves a list of owners which have pools referencing the specified product IDs. If no
* owners are associated with the given products, this method returns an empty list.
*
* @param productIds
* The product IDs for which to retrieve owners
*
* @return
* a list of owners associated with the specified products
*/
@SuppressWarnings("checkstyle:indentation")
public CandlepinQuery<Owner> lookupOwnersWithProduct(Collection<String> productIds) {
if (productIds != null && !productIds.isEmpty()) {
Session session = this.currentSession();
// Impl note:
// We have to break this up into two queries for proper cursor and pagination support.
// Hibernate currently has two nasty "features" which break these in their own special
// way:
// - Distinct, when applied in any way outside of direct SQL, happens in Hibernate
// *after* the results are pulled down, if and only if the results are fetched as a
// list. The filtering does not happen when the results are fetched with a cursor.
// - Because result limiting (first+last result specifications) happens at the query
// level and distinct filtering does not, cursor-based pagination breaks due to
// potential results being removed after a page of results is fetched.
Criteria idCriteria = session.createCriteria(Owner.class, "Owner")
.setProjection(Projections.distinct(Projections.id()))
.createAlias("Owner.pools", "Pool")
.createAlias("Pool.product", "Prod", JoinType.LEFT_OUTER_JOIN)
.createAlias("Pool.derivedProduct", "DProd", JoinType.LEFT_OUTER_JOIN)
.createAlias("Pool.providedProducts", "PProd", JoinType.LEFT_OUTER_JOIN)
.createAlias("Pool.derivedProvidedProducts", "DPProd", JoinType.LEFT_OUTER_JOIN)
.add(Restrictions.or(
CPRestrictions.in("Prod.id", productIds),
CPRestrictions.in("DProd.id", productIds),
CPRestrictions.in("PProd.id", productIds),
CPRestrictions.in("DPProd.id", productIds)
));
List<String> ownerIds = idCriteria.list();
if (ownerIds != null && !ownerIds.isEmpty()) {
DetachedCriteria criteria = DetachedCriteria.forClass(Owner.class)
.add(CPRestrictions.in("id", ownerIds));
return this.cpQueryFactory.<Owner>buildQuery(session, criteria);
}
}
return this.cpQueryFactory.<Owner>buildQuery();
}
public CandlepinQuery<String> getConsumerIds(Owner owner) {
return this.getConsumerIds(owner.getId());
}
@SuppressWarnings("unchecked")
public CandlepinQuery<String> getConsumerIds(String ownerId) {
DetachedCriteria criteria = DetachedCriteria.forClass(Consumer.class)
.add(Restrictions.eq("owner.id", ownerId))
.setProjection(Property.forName("id"));
return this.cpQueryFactory.<String>buildQuery(this.currentSession(), criteria);
}
public CandlepinQuery<String> getConsumerUuids(Owner owner) {
return this.getConsumerUuids(owner.getId());
}
@SuppressWarnings("unchecked")
public CandlepinQuery<String> getConsumerUuids(String ownerId) {
DetachedCriteria criteria = DetachedCriteria.forClass(Consumer.class)
.add(Restrictions.eq("owner.id", ownerId))
.setProjection(Property.forName("uuid"));
return this.cpQueryFactory.<String>buildQuery(this.currentSession(), criteria);
}
}