package com.clouck.repository; import static org.springframework.data.mongodb.core.query.Criteria.where; import java.util.Collection; import java.util.List; import org.apache.commons.lang3.Validate; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Repository; import com.clouck.exception.ClouckUnexpectedConditionException; import com.clouck.model.Region; import com.clouck.model.ResourceType; import com.clouck.model.aws.AbstractResource; import com.clouck.model.aws.ec2.Ec2Version; import com.clouck.model.aws.ec2.Ec2VersionMeta; import com.google.common.base.Optional; import com.google.common.collect.Lists; @Repository public class AwsRepositoryImpl implements AwsRepository { private static final Logger log = LoggerFactory.getLogger(AwsRepositoryImpl.class); @Autowired private MongoOperations mongoOps; private Query createQuery(String accountId, ResourceType resourceType, Region region, DateTime dt, Boolean isIncludeTime, Boolean isAsc, boolean isUptoOrFrom, Pageable pageable) { Query query = new Query(createCriteria(accountId, resourceType, region, dt, isIncludeTime, isUptoOrFrom)); if (isAsc != null) { if (isAsc) { query.with(new Sort(Direction.ASC, "timeDetected")); } else { query.with(new Sort(Direction.DESC, "timeDetected")); } } if (pageable != null) { query.with(pageable); } return query; } private Query createQuery(Criteria criteria, Boolean isAsc, Pageable pageable) { Query query = new Query(criteria); if (isAsc != null) { if (isAsc) { query.with(new Sort(Direction.ASC, "timeDetected")); } else { query.with(new Sort(Direction.DESC, "timeDetected")); } } if (pageable != null) { query.with(pageable); } return query; } private Criteria createCriteria(String accountId, ResourceType resourceType, Region region, DateTime dt, Boolean isIncludeTime, boolean isUptoOrFrom) { Validate.notNull(accountId); Validate.isTrue((dt != null && isIncludeTime != null) || (dt == null && isIncludeTime == null)); Validate.isTrue(region == null ? true : !region.equals(Region.All)); Criteria criteria = where("accountId").is(accountId); if (resourceType != null) { criteria = criteria.and("resourceType").is(resourceType); } if (region != null) { criteria = criteria.and("region").is(region); } if (dt != null) { if (isIncludeTime) { if (isUptoOrFrom) { criteria = criteria.and("timeDetected").lte(dt.toDate()); } else { criteria = criteria.and("timeDetected").gte(dt.toDate()); } } else { if (isUptoOrFrom) { criteria = criteria.and("timeDetected").lt(dt.toDate()); } else { criteria = criteria.and("timeDetected").gt(dt.toDate()); } } } return criteria; } @Override public Optional<Ec2Version> findEc2VersionUpto(String accountId, ResourceType resourceType, Region region, DateTime dt, Boolean isIncludeTime, boolean isAsc) { Query query = createQuery(accountId, resourceType, region, dt, isIncludeTime, isAsc, true, null); Ec2Version result = mongoOps.findOne(query, Ec2Version.class); if (result != null) { return Optional.of(result); } else { return Optional.absent(); } } @Override public List<Ec2Version> findEc2VersionsUpto(String accountId, ResourceType resourceType, Region region, DateTime dt, Boolean isIncludeTime, boolean isAsc) { Query query = createQuery(accountId, resourceType, region, dt, isIncludeTime, isAsc, true, null); return mongoOps.find(query, Ec2Version.class); } @Override public long countEc2VersionsUpto(String accountId, ResourceType resourceType, Region region, DateTime dt, Boolean isIncludeTime) { Query query = createQuery(accountId, resourceType, region, dt, isIncludeTime, null, true, null); return mongoOps.count(query, Ec2Version.class); } @Override public List<Ec2Version> findEc2VersionsFrom(String accountId, ResourceType resourceType, Region region, DateTime dt, Boolean isIncludeTime, Boolean isAsc) { Query query = createQuery(accountId, resourceType, region, dt, isIncludeTime, isAsc, false, null); return mongoOps.find(query, Ec2Version.class); } @Override public Optional<Ec2Version> findEc2VersionAt(String accountId, ResourceType resourceType, DateTime dateTime) { Ec2Version result = mongoOps.findOne( new Query(where("accountId").is(accountId). and("resourceType").is(resourceType). and("timeDetected").is(dateTime.toDate())), Ec2Version.class); if (result != null) { return Optional.of(result); } else { return Optional.absent(); } } @Override public long countEc2VersionMetasUpto(String accountId, ResourceType resourceType, Region region, DateTime dt, Boolean isIncludeTime, String uniqueId) { Criteria criteria = createCriteria(accountId, resourceType, region, dt, isIncludeTime, true); if (uniqueId != null) { criteria = criteria.and("events.uniqueId").is(uniqueId); } Query query = createQuery(criteria, null, null); return mongoOps.count(query, Ec2VersionMeta.class); } @Override public Optional<Ec2VersionMeta> findEc2VersionMetaUpto(String accountId, ResourceType resourceType, Region region, DateTime dt, Boolean isIncludeTime, boolean isAsc) { Query query = createQuery(accountId, resourceType, region, dt, isIncludeTime, isAsc, true, null); Ec2VersionMeta result = mongoOps.findOne(query, Ec2VersionMeta.class); if (result != null) { return Optional.of(result); } else { return Optional.absent(); } } @Override public List<Ec2VersionMeta> findEc2VersionMetasUpto(String accountId, ResourceType resourceType, Region region, DateTime dt, Boolean isIncludeTime, boolean isAsc, Pageable pageable, String uniqueId) { Criteria criteria = createCriteria(accountId, resourceType, region, dt, isIncludeTime, true); if (uniqueId != null) { criteria = criteria.and("events.uniqueId").is(uniqueId); } Query query = createQuery(criteria, isAsc, pageable); return mongoOps.find(query, Ec2VersionMeta.class); } @Override public List<Ec2VersionMeta> findEc2VersionMetasOrderByTimeDetectedDesc(String accountId, ResourceType rt, Region region, String uniqueId) { Criteria criteria = where("accountId").is(accountId).and("resourceType").is(rt).and("events.uniqueId").is(uniqueId); if (region != null) { criteria = criteria.and("region").is(region); } Query query = new Query(criteria).with(new Sort(Direction.DESC, "timeDetected")); return mongoOps.find(query, Ec2VersionMeta.class); } @Override @SuppressWarnings("unchecked") public List<AbstractResource<?>> findResources(Collection<String> ids, ResourceType resourceType) { return (List<AbstractResource<?>>) mongoOps.find(new Query(where("id").in(ids)), resourceType.getResourceClass()); } @Override @SuppressWarnings("rawtypes") public Optional<AbstractResource> findResource(String resourceId, ResourceType resourceType) { AbstractResource result = mongoOps.findOne( new Query(where("id").is(resourceId)), resourceType.getResourceClass()); if (result != null) { return Optional.of(result); } else { return Optional.absent(); } } @Override public List<? extends AbstractResource<?>> findResource(ResourceType resourceType, String accountId, String uniqueId) { return findResource(resourceType, accountId, uniqueId, null); } @Override public List<? extends AbstractResource<?>> findResource(ResourceType resourceType, String accountId, String uniqueId, String secondUniqueId) { List<String> uniqueIdNames = Lists.newArrayList(resourceType.getUniqueIdNames()); switch (uniqueIdNames.size()) { case 1: return mongoOps.find( new Query(where("resource." + uniqueIdNames.get(0)).is(uniqueId). and("accountId").is(accountId)). with(new Sort(Direction.DESC, "timeDetected")), resourceType.getResourceClass()); case 2: return mongoOps.find( new Query(where("resource." + uniqueIdNames.get(0)).is(uniqueId). and("resource." + uniqueIdNames.get(1)).is(secondUniqueId). and("accountId").is(accountId)). with(new Sort(Direction.DESC, "timeDetected")), resourceType.getResourceClass()); default: throw new ClouckUnexpectedConditionException("up to now, should only support up to two combinations"); } } }