/**
* Copyright (c) 2012, The National Archives <pronom@nationalarchives.gsi.gov.uk>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the The National Archives nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package uk.gov.nationalarchives.droid.planet.xml.dao;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import uk.gov.nationalarchives.droid.core.interfaces.NodeStatus;
import uk.gov.nationalarchives.droid.core.interfaces.ResourceType;
import uk.gov.nationalarchives.droid.core.interfaces.filter.Filter;
import uk.gov.nationalarchives.droid.core.interfaces.filter.FilterCriterion;
import uk.gov.nationalarchives.droid.core.interfaces.filter.RestrictionFactory;
import uk.gov.nationalarchives.droid.core.interfaces.filter.expressions.Junction;
import uk.gov.nationalarchives.droid.core.interfaces.filter.expressions.QueryBuilder;
import uk.gov.nationalarchives.droid.core.interfaces.filter.expressions.Restrictions;
import uk.gov.nationalarchives.droid.profile.referencedata.Format;
/**
* JPA implementation of JpaPlanetsXMLDaoImpl.
*
* @author Alok Kumar Dash.
*/
public class JpaPlanetsXMLDaoImpl implements PlanetsXMLDao {
private static final int THREE = 3;
private static final String ZERO = "0";
private String filterQueryString = "";
//private Map<String, Object> filterQueryParameterMap;
private Object[] filterParams;
private boolean filterEnabled;
private final Log log = LogFactory.getLog(getClass());
@PersistenceContext
private EntityManager entityManager;
/**
* Flushes the DROID entity manager.
*/
void flush() {
entityManager.flush();
}
/**
* {@inheritDoc}
*/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public PlanetsXMLData getDataForPlanetsXML(Filter filter) {
filterQueryString = "";
if (filter != null) {
filterEnabled = filter.isEnabled() && !filter.getCriteria().isEmpty();
}
if (filterEnabled) {
QueryBuilder queryBuilder = QueryBuilder.forAlias("profileResourceNode");
if (filter.isNarrowed()) {
for (FilterCriterion criterion : filter.getCriteria()) {
queryBuilder.add(RestrictionFactory.forFilterCriterion(criterion));
}
} else {
Junction orJunction = Restrictions.disjunction();
for (FilterCriterion criterion : filter.getCriteria()) {
orJunction.add(RestrictionFactory.forFilterCriterion(criterion));
}
queryBuilder.add(orJunction);
}
filterQueryString = " AND " + queryBuilder.toEjbQl();
filterParams = queryBuilder.getValues();
// FilterQueryStringGenerator filterQueryGenerator = new FilterQueryStringGenerator();
// FilterQueryStringGenerator.FilterQueryStringAndNamedParameter queryAndParameter = filterQueryGenerator
// .getFilterQueryString(filter);
// filterQueryString = " AND " + queryAndParameter.getFilterQueryString();
// filterQueryParameterMap = queryAndParameter.getNamesParameterMap();
}
PlanetsXMLData planetXMLData = new PlanetsXMLData();
planetXMLData.setProfileStat(getProfileStat());
planetXMLData.setGroupByPuid(getGroupByPuid());
planetXMLData.setGroupByYear(getGroupByYear());
return planetXMLData;
}
/**
*
*/
private void setFilterParameters(Query q, int startPosition) {
if (filterEnabled) {
int pos = startPosition;
for (Object param : filterParams) {
q.setParameter(pos++, param);
}
//
//
// for (String parameterKey : filterQueryParameterMap.keySet()) {
// log.info("The Parameter is : " + parameterKey);
//
// if (filterQueryParameterMap.get(parameterKey) instanceof String) {
// q.setParameter(parameterKey, filterQueryParameterMap.get(parameterKey));
// log.info("The Parameter Value is : "
// + filterQueryParameterMap.get(parameterKey));
// } else if (filterQueryParameterMap.get(parameterKey) instanceof Long) {
// q.setParameter(parameterKey, filterQueryParameterMap.get(parameterKey));
// log.info("The Parameter Value is : "
// + filterQueryParameterMap.get(parameterKey));
// }
// }
}
}
private ProfileStat getProfileStat() {
ProfileStat profileStat = new ProfileStat();
Query q = entityManager
.createQuery("SELECT min(profileResourceNode.metaData.size), max(profileResourceNode.metaData.size), "
+ "avg(profileResourceNode.metaData.size), sum(profileResourceNode.metaData.size) "
+ " from ProfileResourceNode profileResourceNode "
+ "where profileResourceNode.metaData.resourceType != ? "
+ filterQueryString);
int paramIndex = 1;
q.setParameter(paramIndex++, ResourceType.FOLDER);
setFilterParameters(q, paramIndex);
List<?> results = q.getResultList();
if (results != null && !results.isEmpty()) {
for (Object res : results) {
Object[] aaa = (Object[]) res;
BigInteger bigInt = (aaa[0] == null) ? new BigInteger(ZERO)
: new BigInteger(aaa[0].toString());
profileStat.setProfileSmallestSize(bigInt);
bigInt = (aaa[1] == null) ? new BigInteger(ZERO)
: new BigInteger(aaa[1].toString());
profileStat.setProfileLargestSize(bigInt);
BigDecimal bigDec = (aaa[2] == null) ? new BigDecimal(ZERO)
: new BigDecimal(aaa[2].toString());
profileStat.setProfileMeanSize(bigDec);
bigInt = (aaa[THREE] == null) ? new BigInteger(ZERO)
: new BigInteger(aaa[THREE].toString());
profileStat.setProfileTotalSize(bigInt);
}
}
setTotalUnreadableFiles(profileStat);
setTotalUnreadableFolders(profileStat);
setTotalReadableFiles(profileStat);
return profileStat;
}
/**
* @param profileStat
*/
private void setTotalReadableFiles(ProfileStat profileStat) {
Query queryForTotalReadableFiles = entityManager
.createQuery("SELECT count(*) "
+ "from ProfileResourceNode profileResourceNode "
+ "where metaData.nodeStatus not in (?, ?) "
+ "and (metaData.resourceType = 0 or metaData.resourceType != ?) "
+ filterQueryString);
int index = 1;
queryForTotalReadableFiles.setParameter(index++, NodeStatus.ACCESS_DENIED);
queryForTotalReadableFiles.setParameter(index++, NodeStatus.NOT_FOUND);
queryForTotalReadableFiles.setParameter(index++, ResourceType.FOLDER);
setFilterParameters(queryForTotalReadableFiles, index);
List<?> results = queryForTotalReadableFiles.getResultList();
if (results != null && !results.isEmpty()) {
for (Object res : results) {
profileStat.setProfileTotalReadableFiles(new BigInteger(res
.toString()));
}
}
}
/**
* @param profileStat
*/
private void setTotalUnreadableFolders(ProfileStat profileStat) {
Query queryForTotalUnreadableFolders = entityManager
.createQuery("SELECT count(*) "
+ "from ProfileResourceNode profileResourceNode "
+ "where (metaData.nodeStatus = ? or metaData.nodeStatus = ?) "
+ "and metaData.resourceType = ? "
+ filterQueryString);
int index = 1;
queryForTotalUnreadableFolders.setParameter(index++, NodeStatus.ACCESS_DENIED);
queryForTotalUnreadableFolders.setParameter(index++, NodeStatus.NOT_FOUND);
queryForTotalUnreadableFolders.setParameter(index++, ResourceType.FOLDER);
setFilterParameters(queryForTotalUnreadableFolders, index);
List<?> results = queryForTotalUnreadableFolders.getResultList();
if (results != null && !results.isEmpty()) {
for (Object res : results) {
profileStat.setProfileTotalUnReadableFolders(new BigInteger(res
.toString()));
}
}
}
/**
* @param profileStat
*/
private void setTotalUnreadableFiles(ProfileStat profileStat) {
Query queryForTotalUnreadableFiles = entityManager
.createQuery("SELECT count(*) "
+ "from ProfileResourceNode profileResourceNode "
+ "where (metaData.nodeStatus = ? or metaData.nodeStatus = ?) "
+ "and metaData.resourceType != ? "
+ filterQueryString);
int index = 1;
queryForTotalUnreadableFiles.setParameter(index++, NodeStatus.ACCESS_DENIED);
queryForTotalUnreadableFiles.setParameter(index++, NodeStatus.NOT_FOUND);
queryForTotalUnreadableFiles.setParameter(index++, ResourceType.FOLDER);
setFilterParameters(queryForTotalUnreadableFiles, index);
List<?> results = queryForTotalUnreadableFiles.getResultList();
if (results != null && !results.isEmpty()) {
for (Object res : results) {
profileStat.setProfileTotalUnReadableFiles(new BigInteger(res
.toString()));
}
}
}
private List<GroupByYearSizeAndCountRow> getGroupByYear() {
List<GroupByYearSizeAndCountRow> dataList = new ArrayList<GroupByYearSizeAndCountRow>();
GroupByYearSizeAndCountRow groupByYearSizeAndCountRow = null;
Query q = entityManager
.createQuery("SELECT year(profileResourceNode.metaData.lastModifiedDate), "
+ "count(*), sum(profileResourceNode.metaData.size) "
+ "from ProfileResourceNode profileResourceNode "
+ "where profileResourceNode.metaData.resourceType != ? "
+ filterQueryString
+ " group by year(profileResourceNode.metaData.lastModifiedDate) ");
int index = 1;
q.setParameter(index++, ResourceType.FOLDER);
setFilterParameters(q, index);
List<?> results = q.getResultList();
if (results != null && !results.isEmpty()) {
for (Object res : results) {
groupByYearSizeAndCountRow = new GroupByYearSizeAndCountRow();
Object[] aaa = (Object[]) res;
if (aaa[0] != null) {
groupByYearSizeAndCountRow.setYear(new Integer(aaa[0]
.toString()));
}
if (aaa[1] != null) {
groupByYearSizeAndCountRow.setCount(new BigInteger(aaa[1]
.toString()));
}
if (aaa[2] != null) {
groupByYearSizeAndCountRow.setSize(new BigDecimal(aaa[2]
.toString()));
}
dataList.add(groupByYearSizeAndCountRow);
}
}
return dataList;
}
private List<GroupByPuidSizeAndCountRow> getGroupByPuid() {
List<GroupByPuidSizeAndCountRow> dataList = new ArrayList<GroupByPuidSizeAndCountRow>();
GroupByPuidSizeAndCountRow groupByPuidSizeAndCountRow = null;
Query q = entityManager
.createQuery("SELECT f.puid, count(*), sum(profileResourceNode.metaData.size) "
+ "from ProfileResourceNode profileResourceNode "
+ "inner join profileResourceNode.formatIdentifications f "
+ "where profileResourceNode.metaData.resourceType != ? "
+ filterQueryString + " group by f.puid ");
int index = 1;
q.setParameter(index++, ResourceType.FOLDER);
setFilterParameters(q, index);
List<?> results = q.getResultList();
if (results != null && !results.isEmpty()) {
for (Object res : results) {
groupByPuidSizeAndCountRow = new GroupByPuidSizeAndCountRow();
Object[] aaa = (Object[]) res;
String puid = "";
if (aaa[0] != null) {
puid = new String(aaa[0].toString());
}
groupByPuidSizeAndCountRow.setPuid(puid);
if (aaa[1] != null) {
groupByPuidSizeAndCountRow.setCount(new BigInteger(aaa[1]
.toString()));
}
if (aaa[2] != null) {
groupByPuidSizeAndCountRow.setSize(new BigDecimal(aaa[2]
.toString()));
}
// FIXME: N + 1 SELECTS ??????? WHY???
String query = "from Format where puid =:puid";
Query detailsQuery = entityManager.createQuery(query);
detailsQuery.setParameter("puid", puid);
Format format = (Format) detailsQuery.getSingleResult();
groupByPuidSizeAndCountRow.setFormatName(format.getName());
groupByPuidSizeAndCountRow
.setFormatVersion(format.getVersion());
groupByPuidSizeAndCountRow.setMimeType(format.getMimeType());
dataList.add(groupByPuidSizeAndCountRow);
}
}
return dataList;
}
}