/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package beans.report.selectors.disease.sicklist;
import beans.report.selectors.data.DateRange;
import beans.report.selectors.disease.DeseaseDataSelector;
import beans.report.selectors.disease.DiseaseLine;
import beans.directory.mkb10.entity.Mkb10;
import beans.directory.simple.entities.DisabilityType;
import beans.doctor.sicklist.entity.Sicklist;
import framework.beans.directory.simple.entities.Sex;
import framework.generic.ClipsServerException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
/**
*
* @author finder
*/
abstract public class SickListDataSelector extends DeseaseDataSelector<SicklistTableLineData, SickListDataSelector.SickListElement> {
private enum SelectType{
notRef,
ref,
notClosedAndRef
}
static protected class SickListElement implements Comparable<SickListElement>{
private Integer id;
private Date dateOpen;
private Date dateClose;
private DisabilityType disType;
private Mkb10 diag;
private Date clientBorn;
private Sex clientSex;
private Integer refID;
public SickListElement refItem;
public SickListElement(Integer id, Date dateOpen, Date dateClose,
DisabilityType disType, Mkb10 diag, Date clientBorn,
Sex clientSex) {
this.id = id;
this.dateOpen = dateOpen;
this.dateClose = dateClose;
this.disType = disType;
this.diag = diag;
this.clientBorn = clientBorn;
this.clientSex = clientSex;
}
public SickListElement(Integer id, Integer refID){
this.id = id;
this.refID = refID;
}
@Override
public int compareTo(SickListElement o) {
return id - o.id;
}
public Integer getId() {
return id;
}
public Date getDateOpen() {
return dateOpen;
}
public Date getDateClose() {
return dateClose;
}
public DisabilityType getDisType() {
return disType;
}
public Mkb10 getDiag() {
return diag;
}
public Date getClientBorn() {
return clientBorn;
}
public Sex getClientSex() {
return clientSex;
}
public Integer getRefID() {
return refID;
}
public void setRefID(Integer refID) {
this.refID = refID;
}
public SickListElement getRefItem() {
return refItem;
}
public void setRefItem(SickListElement refItem) {
this.refItem = refItem;
}
}
public SickListDataSelector(EntityManager manager, ArrayList<DiseaseLine> lines) {
super(manager, lines);
}
@Override
protected Mkb10 getMkbForItem(SickListElement item) {
return item.getDiag();
}
protected String getSpecialSql(){
return "";
}
protected static final int OFF_ID = 0;
protected static final int OFF_DATE_OPEN = 1;
protected static final int OFF_DATE_CLOSE = 2;
protected static final int OFF_DISABILITY_TYPE = 3;
protected static final int OFF_MKB = 4;
protected static final int OFF_CLIENT_BORN = 5;
protected static final int OFF_CLIENT_SEX = 6;
protected static final int OFF_REFERENCED_ID = 7;
private String getSelectString(final SelectType type){
switch (type){
case notRef:
return "SELECT a.id, " +
"a.dateOpen, " +
"a.dateToWork, " +
"a.disabilityType, " +
"a.diagClose.mkb10, " +
"a.diagClose.serviceRender.disease.emc.client.born, " +
"a.diagClose.serviceRender.disease.emc.client.sex " +
" FROM " + Sicklist.class.getSimpleName() + " AS a";
case ref:
return "SELECT a.id, " +
"a.dateOpen, " +
"a.dateToWork," +
"a.disabilityType, " +
"a.diagClose.mkb10," +
"a.diagClose.serviceRender.disease.emc.client.born, " +
"a.diagClose.serviceRender.disease.emc.client.sex, " +
"a.referenced.id " +
" FROM " + Sicklist.class.getSimpleName() + " AS a";
case notClosedAndRef:
return "SELECT a.id," +
"a.referenced.id" +
" FROM " + Sicklist.class.getSimpleName() + " AS a";
default:
throw new RuntimeException();
}
}
private SickListElement transform(Object[] objects, final SelectType type){
if (type == SelectType.notClosedAndRef){
SickListElement el = new SickListElement((Integer)objects[OFF_ID], (Integer)objects[1]);
return el;
}
else{
SickListElement el = new SickListElement((Integer)objects[OFF_ID],
(Date)objects[OFF_DATE_OPEN],
(Date)objects[OFF_DATE_CLOSE],
(DisabilityType)objects[OFF_DISABILITY_TYPE],
(Mkb10)objects[OFF_MKB],
(Date)objects[OFF_CLIENT_BORN],
(Sex)objects[OFF_CLIENT_SEX]);
if (type == SelectType.ref){
el.setRefID((Integer)objects[OFF_REFERENCED_ID]);
}
return el;
}
}
private ArrayList<SickListElement> getSicklistList(DateRange timeRange, SelectType type){
String sql = getSelectString(type) + " WHERE ";
switch (type){
case notRef:
sql += "a.dateToWork >= :begin and a.dateToWork < :end and a.referenced is null";
break;
case ref:
sql += "a.dateToWork >= :begin";
break;
case notClosedAndRef:
sql += "a.dateOpen >= :begin and a.dateToWork is null";
break;
default:
throw new RuntimeException();
}
Query query = manager.createQuery(sql);
switch (type){
case notRef:
query.setParameter("begin", timeRange.begin);
query.setParameter("end", timeRange.end);
break;
case ref:
case notClosedAndRef:
query.setParameter("begin", timeRange.begin);
break;
default:
throw new RuntimeException();
}
@SuppressWarnings("unchecked")
List<Object[]> data = query.getResultList();
ArrayList<SickListElement> target = new ArrayList<SickListElement>(data.size());
for (Object[] objects : data) {
target.add(transform(objects, type));
}
return target;
}
private SickListElement getSicklistByID(Integer id, SelectType type){
String sql = getSelectString(type) + " WHERE a.id = :id";
Query query = manager.createQuery(sql);
query.setParameter("id", id);
@SuppressWarnings("unchecked")
List<Object[]> data = query.getResultList();
if (data.size() != 0){
return transform(data.get(0), type);
}
return null;
}
private SickListElement getSicklistByID(Integer id){
SickListElement target = getSicklistByID(id, SelectType.notRef);
if (target == null){
target = getSicklistByID(id, SelectType.ref);
}
return target;
}
private void loadRecursiveAndLink(HashMap<Integer, SickListElement> map, HashSet<Integer> removed, SickListElement sickListElement){
if (sickListElement.getRefItem() != null){
return;
}
Integer ref = sickListElement.getRefID();
if (ref == null || removed.contains(ref)){
return;
}
removed.add(ref);
SickListElement refEl = map.remove(ref);
if (refEl == null){
refEl = getSicklistByID(ref);
}
sickListElement.setRefItem(refEl);
if (refEl != null){
loadRecursiveAndLink(map, removed, refEl);
}
}
private void removeRecursive(HashMap<Integer, SickListElement> map, HashSet<Integer> removed, SickListElement sickListElement){
SickListElement cur = sickListElement;
map.remove(cur.getId());
removed.add(cur.getId());
while (cur != null && cur.getRefID() != null){
removed.add(cur.getRefID());
cur = map.remove(cur.getRefID());
}
}
@Override
public void initDataSet() throws ClipsServerException {
DateRange timeRange = getRange();
ArrayList<SickListElement> base = getSicklistList(timeRange, SelectType.notRef);
HashMap<Integer, SickListElement> map = new HashMap<Integer, SickListElement>(1024);
for (SickListElement sickListElement : base) {
map.put(sickListElement.getId(), sickListElement);
}
ArrayList<SickListElement> exts = getSicklistList(timeRange, SelectType.ref);
for (SickListElement sickListElement : exts) {
map.put(sickListElement.getId(), sickListElement);
}
HashSet<Integer> removed = new HashSet<Integer>();
// удаляем больничные котоые попадут только в следущий отчетный период (закрыты в другом году)
for (int i = 0; i < exts.size(); i++) {
SickListElement sickListElement = exts.get(i);
if (sickListElement.getDateClose().after(timeRange.end)){
removeRecursive(map, removed, sickListElement);
exts.set(i, null);
}
}
// удаляем больничные котоые попадут только в следущий отчетный период (не закрыты)
for (SickListElement element: getSicklistList(timeRange, SelectType.notClosedAndRef)){
removeRecursive(map, removed, element);
}
/* собираем связанные больничные в списки в соотведствии с пунктом:
* Если случай ВН был зафиксирован в предыдущий отчетному период,
* а закончился в отчетном году, то он учитывается по последнему закрытому
* листку временной нетрудоспособности в отчетном году, а в дни
* нетрудоспособности по этому случаю включаются календарные дни как
*
* предыдущего, так и отчетного года.
* чтобы предотвратить двойное включение одного листка в отчет,
* удалаем их из map,
*
*/
for (SickListElement sickListElement : exts) {
if (sickListElement != null){
loadRecursiveAndLink(map, removed, sickListElement);
}
}
ArrayList<SickListElement> target = new ArrayList<SickListElement>(map.values());
setDataSet(target);
}
@Override
protected SicklistTableLineData createDataLine() {
return new SicklistTableLineData();
}
@Override
protected boolean isMale(SickListElement itm) {
return isMaleID(itm.getClientSex().getId());
}
@Override
public void putTableParams(HashMap<String, Object> map, int part) throws ClipsServerException {
// nothing to do
}
@Override
protected int getSelectDataCount() {
throw new UnsupportedOperationException("Not supported yet.");
}
}