package edu.gatech.i3l.fhir.jpa.dao;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.server.IBundleProvider;
import edu.gatech.i3l.fhir.jpa.conf.PropertiesResolver;
import edu.gatech.i3l.fhir.jpa.entity.BaseResourceEntity;
import edu.gatech.i3l.fhir.jpa.entity.IResourceEntity;
import edu.gatech.i3l.fhir.jpa.util.StopWatch;
public class BaseFhirSystemDao<T> implements IFhirSystemDao<T> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseFhirSystemDao.class);
private static final String ENTITIES_PACKAGE_PROP = "ca.uhn.fhir.entities_package";
private BaseFhirDao myBaseFhirDao;
private FhirContext myContext;
@PersistenceContext()
protected EntityManager myEntityManager;
public BaseFhirDao getBaseFhirDao() {
return myBaseFhirDao;
}
public void setBaseFhirDao(BaseFhirDao baseFhirDao) {
this.myBaseFhirDao = baseFhirDao;
}
public FhirContext getContext() {
return myContext;
}
public void setContext(FhirContext myContext) {
this.myContext = myContext;
}
@Override
public IBundleProvider history(Date theSince) {
StopWatch w = new StopWatch();
IBundleProvider retVal = null; //FIXME myBaseFhirDao.history(null, null, theSince);
ourLog.info("Processed global history in {}ms", w.getMillisAndRestart());
return retVal;
}
protected BaseResourceEntity loadFirstEntityFromCandidateMatches(Set<Long> candidateMatches) {
return myEntityManager.find(BaseResourceEntity.class, candidateMatches.iterator().next());//FIXME this should be specific resource type class
}
/**
* @return A map with the provided resource types and how many registries are stored in the database for each resource.
*/
@Override
public Map<String, Long> getResourceCounts() {
Map<String, Long> retVal = new HashMap<String, Long>();
ClassPathScanningCandidateComponentProvider cpsccp = new ClassPathScanningCandidateComponentProvider(false);
TypeFilter filter = new AssignableTypeFilter(IResourceEntity.class);
cpsccp.addIncludeFilter(filter );
cpsccp.setResourceLoader(new PathMatchingResourcePatternResolver(Thread.currentThread().getContextClassLoader()));
String entitiesPackage = PropertiesResolver.getInstance().getPropertyValue(ENTITIES_PACKAGE_PROP);
Set<BeanDefinition> beans = cpsccp.findCandidateComponents(entitiesPackage);
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
for (BeanDefinition beanDefinition : beans) {
String className = beanDefinition.getBeanClassName();
try {
Class<?> defClass = Class.forName(className);
IResourceEntity resEntity = (IResourceEntity) defClass.newInstance();
Class<? extends IBaseResource> resType = myBaseFhirDao.getContext().getResourceDefinition(resEntity.getResourceType()).getImplementingClass();
if(resType != null){
CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
criteria.select(builder.count(criteria.from(defClass)));
Long r = myEntityManager.createQuery(criteria).getSingleResult();
retVal.put(resType.getSimpleName(), r);
}
} catch (ClassNotFoundException e) {
ourLog.error("Resource count: the class {} wasn't found in the classpath.", className);
} catch (InstantiationException e) {
// TODO use mirrors lib
} catch (IllegalAccessException e) {
}
}
return retVal;
}
@Override
public T transaction(T theResources) {
// not needed here
return null;
}
@Override
public void notifyWriteCompleted() {
myBaseFhirDao.notifyWriteCompleted();
}
@Override
public void registerDaoListener(IDaoListener theListener) {
myBaseFhirDao.registerDaoListener(theListener);
}
}