package kr.co.kihyun.beans.entity;



import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.NullValue;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import kr.co.kihyun.beans.entity.ecross.IRemotePersistable;

import kr.co.kihyun.beans.entity.util.QueryImpl;
import kr.co.kihyun.io.IUploadable;
//import kr.co.kihyun.lang.MString;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//import kr.co.kihyun.db.DBManager;

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class TotDoc extends AbstractPublicDocument implements IUploadable, IRemotePersistable{

    /**
     *
     */
    private static final long serialVersionUID = 9200425438952946683L;
    private static final Logger LOG = LoggerFactory.getLogger(TotDoc.class);
    private static final boolean DEFAULT_REPORT_RECURSION = true;
    //v2. 5.static final 필드 변조 가능성 : Update by KWON,HAN
//    public static final int PROCESS_FORM = TotDocProcess.FORM.ordinal();
//    public static final int PROCESS_REG = TotDocProcess.REG.ordinal();
//    public static final int PROCESS_PRSS = TotDocProcess.PRSS.ordinal();
//    public static final int PROCESS_END = TotDocProcess.END.ordinal();
//    public static final int PROCESS_CANCEL = TotDocProcess.CANCEL.ordinal();
//    public static final int PROCESS_REASSIGN = TotDocProcess.REG.ordinal();
//    public static final int PROCESS_READ = TotDocProcess.READ.ordinal();
//    public static final int PROCESS_ALL = TotDocProcess.ALL.ordinal();
//    public static final int ACCESSAUTH_PER = AccessAuth.PER.ordinal();
//    public static final int ACCESSAUTH_DEPT = AccessAuth.DEPT.ordinal();
//    public static final int ACCESSAUTH_PART = AccessAuth.PART.ordinal();
//    public static final int ACCESSAUTH_ALL = AccessAuth.ALL.ordinal();

    //<참고> 아래의 변수는 사용되지 않는다.
    public static final int PROCESS_FORM = TotDocProcess.FORM.ordinal();
    public static final int PROCESS_REG = TotDocProcess.REG.ordinal();
    public static final int PROCESS_PRSS = TotDocProcess.PRSS.ordinal();
    public static final int PROCESS_END = TotDocProcess.END.ordinal();
    public static final int PROCESS_CANCEL = TotDocProcess.CANCEL.ordinal();
    public static final int PROCESS_REASSIGN = TotDocProcess.REG.ordinal();
    public static final int PROCESS_READ = TotDocProcess.READ.ordinal();
    public static final int PROCESS_ALL = TotDocProcess.ALL.ordinal();
    public static final int ACCESSAUTH_PER = AccessAuth.PER.ordinal();
    public static final int ACCESSAUTH_DEPT = AccessAuth.DEPT.ordinal();
    public static final int ACCESSAUTH_PART = AccessAuth.PART.ordinal();
    public static final int ACCESSAUTH_ALL = AccessAuth.ALL.ordinal();
    //==========================================================
    @Persistent
    private String name;
    @Persistent
    private String executionCode;
    @Persistent
    private Long group;
    @Persistent
    private String mUser; // COLUMN: user_id
    @Persistent(nullValue = NullValue.EXCEPTION)
    private Date startDate = Calendar.getInstance().getTime();
    @Persistent(nullValue = NullValue.EXCEPTION)
    private Date endDate = Calendar.getInstance().getTime();
    @Persistent(customValueStrategy = "timestamp", nullValue = NullValue.EXCEPTION)
    private Date regDate;
    @Persistent(nullValue = NullValue.EXCEPTION)
    private AccessAuth accessAuth = AccessAuth.PER;
    @Persistent
    private String form;
    @Persistent
    private TotDoc masterTotDoc; // COLUMN: rep_id
    @Persistent(mappedBy = "slaveTotDoc")
    private TotReport masterTotReport;
    @Persistent(mappedBy = "masterTotDoc")
    private Set<TotDoc> slaveTotDocs;
    @Persistent
    private MDept masterDept; // COLUMN: rep_dept_id
    @Persistent(nullValue = NullValue.EXCEPTION)
    private String isDeleted = "N"; // COLUMN: del_type
    @Persistent(nullValue = NullValue.EXCEPTION)
    private TotDocAppendType appendType = TotDocAppendType.COPY;
    @Persistent
    private TotDocType type = TotDocType.TOT_DOC; // COLUMN: group_id
    /*@Persistent
    private String mDept; //COLUMN: dept_id*/
    @Persistent
    private MDept mDept;
    @Persistent(nullValue = NullValue.EXCEPTION)
    private int fixNum = 0;
    @Persistent
    private String handyName;
    @Persistent(nullValue = NullValue.EXCEPTION)
    private TotRange totRange = TotRange.INTERNAL;
    @Persistent(mappedBy = "totDoc")
    private Board board;
    @Persistent(nullValue = NullValue.EXCEPTION)
    private AcceptanceLimitStrategy acceptanceLimitStrategy = AcceptanceLimitStrategy.create("LimitByDeadlineStrategy", Long.MAX_VALUE);
    @Persistent(mappedBy = "totDoc")
    private List<TotItem> totItems = new ArrayList<TotItem>();
    @Persistent(mappedBy = "totDoc")
    private Set<TotReport> totReports = new HashSet<TotReport>();
    @Persistent(mappedBy = "totDoc")
    private Set<TotTable> totTables = new HashSet<TotTable>();

    @Persistent(nullValue = NullValue.DEFAULT)
    private String autoRtnYn = "Y";                   //자동회수여부(기본값:Y.자동회수)
    @Persistent(nullValue = NullValue.DEFAULT)
    private String periodicalDocYn = "N";             //정기집계여부(기본값:N.수시집계)

    public TotDoc() {
    }

    public TotDoc(String name, MDept dept, String form) {
        this.setName(name);
        this.setDept(dept);
        this.setForm(form);
    }

    public String getAutoRtnYn() {
        return autoRtnYn;
    }

    public void setAutoRtnYn(String autoRtnYn) {
        this.autoRtnYn = autoRtnYn;
    }

    public String getPeriodicalDocYn() {
        return periodicalDocYn;
    }

    public void setPeriodicalDocYn(String periodicalDocYn) {
        this.periodicalDocYn = periodicalDocYn;
    }

    public String getName() {
        return this.name;
    }

    public final void setName(String name) {
        this.name = name;
    }

    public final ExecutionCode getExecutionCode() {
        try {
            if (executionCode != null) {
                return ExecutionCode.valueOf(executionCode);
            } else {
                return new ExecutionCode(executionCode, null, null);
            }
        } catch (Exception e) {
            LOG.error("Unable to parse execution code for {}", executionCode);
            return new ExecutionCode(executionCode, null, null);
        }
    }

    public final void setExecutionCode(ExecutionCode executionCode) {
        this.executionCode = executionCode == null ? null : executionCode.toString();
    }

    public MUser getUser(PersistenceManager pm) {
        try {
            return pm.getObjectById(MUser.class, this.mUser);
        } catch (JDOObjectNotFoundException jonfe) {
            MUser nullUser = new MUser();
            nullUser.setId(this.mUser);
            return nullUser;
        }
    }

    public final void setUser(MUser mUser) {
        if (mUser == null) {
            this.mUser = null;
            setOwnerEmail(null);
            setOwnerName(null);
            setOwnerPhone(null);
        } else {
            LOG.debug("tot doc user id: {}", mUser.getId());
            this.mUser = mUser.getId();
            setOwnerEmail(mUser.getEmail());
            setOwnerName(mUser.getEncName());
            setOwnerPhone(mUser.getPhone());
        }
    }

    public String getUser()
    {
        return mUser;
    }

    public Date getStartDate() {
        //            미진행자료에 시간을 표기하기 위하여 아래 내용을 주석처리함.
//		if (this.startDate.after(new Date()) &&
//				this.getAcceptanceLimitStrategy().getProcess() == TotDocProcess.PRSS)
//			return null;
//		if (this.getAcceptanceLimitStrategy().getProcess() == TotDocProcess.REG)
//			return startDate;
//
        return this.startDate;
    }

    public void setStartDate(Date stDate) {
        this.startDate = stDate;
    }

    public Date getEndDate() {
        return this.endDate;
    }

    public void setEndDate(Date edDate) {
        this.endDate = edDate;
    }

    public Date getRegDate() {
        return this.regDate;
    }

    public void setRegDate(Date regDate) {
        this.regDate = regDate;
    }

    public AccessAuth getAccessAuth() {
        return this.accessAuth;
    }

    public void setAccessAuth(AccessAuth accAuth) {
        this.accessAuth = accAuth;
    }

    public String getForm() {
        return this.form;
    }

    public final void setForm(String form) {
        this.form = form;
    }

    public TotDoc getMasterTotDoc() {
        return this.masterTotDoc;
    }

    public void setMasterTotDoc(TotDoc doc) {
        this.masterTotDoc = doc;
    }

    public Set<TotDoc> getSlaveTotDocs() {
        return Collections.unmodifiableSet(this.slaveTotDocs);
    }

    public String getRepDept() {
         if (masterDept == null) {
            return null;
        }
        return this.masterDept.getId();
    }

    public MDept getRepDept(PersistenceManager pm) {
        if (masterDept == null) {
            return null;
        }
        return pm.getObjectById(MDept.class, this.masterDept.getId());
    }

    public void setRepDept(MDept masterDept) {
        if (masterDept == null) {
            this.masterDept = null;
        } else {
            this.masterDept = masterDept;
        }
    }

    public String isDeleted() {
        return this.isDeleted;
    }

    public void setDeleted(String isDeleted) {
        this.isDeleted = isDeleted;
    }

    public TotDocProcess getProcess(PersistenceManager pm) {
        return this.getAcceptanceLimitStrategy().getProcess(pm);
    }

    public void setProcess(TotDocProcess p) {
        this.getAcceptanceLimitStrategy().setProcess(p);
    }

    public void setAppendType(TotDocAppendType appendType) {
        this.appendType = appendType;
    }

    public TotDocAppendType getAppendType() {
        return appendType;
    }

    public TotDocType getType() {
        return this.type;
    }

    public void setType(TotDocType t) {
        this.type = t;
    }

    public String getDept() {
        return this.mDept.getId();
    }

    public MDept getDept(PersistenceManager pm) {
        try {
            return pm.getObjectById(MDept.class, this.mDept.getId());
        } catch (JDOObjectNotFoundException jonfe) {
            return null;
        }
    }

    public final void setDept(MDept mDept) {
        if (mDept == null) {
            this.mDept = null;
        } else {
            this.mDept = mDept;
        }
    }

    public int getFixNum() {
        return this.fixNum;
    }

    public void setFixNum(int num) {
        this.fixNum = num;
    }

    public String getHandyName() {
        return this.handyName;
    }

    public void setHandyName(String name) {
        this.handyName = name;
    }

    @Override
	public Map<String, List<Byte>> getAttachments() {
        return this.getBoard().getAttachments();
    }

    @Override
	public void addAttachment(String key, List<Byte> value) {
        this.getBoard().addAttachment(key, value);
    }

    @Override
	public List<Byte> removeAttachment(String key) {
        return this.getBoard().removeAttachment(key);
    }

    /**
     * @return the masterTotReport
     */
    public TotReport getMasterTotReport() {
        return masterTotReport;
    }

    /**
     * @param masterTotReport the masterTotReport to set
     */
    public void setMasterTotReport(TotReport masterTotReport) {
        this.masterTotReport = masterTotReport;
    }

    public static enum TotRange {

        INTERNAL("내부집계"), EXTERNAL("기관학교집계");
        private String name;

        private TotRange(String name) {
            this.name = name;
        }

      //v2. 5.static final 필드 변조 가능성 : Update by KWON,HAN
      //private는 같은 클래스 내에서만 호출이 가능하므로 접근제한이 없는 public으로 하고 final을 사용하지 않는다
//        public static final TotRange asTotRange(int rangeNum) {
        public static TotRange asTotRange(int rangeNum) {
            //LOG.debug("v2. 5.static final 필드 변조 가능성 : TotDoc.asTotRange() values()[rangeNum]={}, Test OK", values()[rangeNum]);
            return values()[rangeNum];
        }
      //==========================================================

        @Override
        public String toString() {
            return name;
        }
    }

    public TotRange getTotRange() {
        return this.totRange;
    }

    public void setTotRange(TotRange r) {
        this.totRange = r;
    }

    public Board getBoard() {
        return this.board;
    }

    public void setBoard(Board board) {
        this.board = board;
    }

    public final AcceptanceLimitStrategy getAcceptanceLimitStrategy() {
        return this.acceptanceLimitStrategy;
    }

    public final void setAcceptanceLimitStrategy(AcceptanceLimitStrategy acceptanceLimitStrategy) {
        this.acceptanceLimitStrategy = acceptanceLimitStrategy;
    }

    public List<TotItem> getTotItems() {
        return Collections.unmodifiableList(this.totItems);
    }

    public void addItem(TotItem item) {
        this.totItems.add(item);
    }

    public void removeTotItem(TotItem item) {
        this.totItems.remove(item);
    }

    public Set<TotReport> getTotReports() {
        return Collections.unmodifiableSet(this.totReports);
    }

    public void addTotReport(TotReport totReport) {
        this.totReports.add(totReport);
    }

    public void removeTotReport(TotReport totReport) {
        this.totReports.remove(totReport);
    }

    public Set<TotTable> getTotTables() {
        return Collections.unmodifiableSet(this.totTables);
    }

    public void addTotTable(TotTable totTable) {
        this.totTables.add(totTable);
    }

    public void removeTotTable(TotTable totTable) {
        this.totTables.remove(totTable);
    }

    public void setGroup(Long group) {
        this.group = group;
    }

    public Long getGroup() {
        return group;
    }

    public List<Board> getBoards(PersistenceManager pm, Category category) {
        return this.getBoards(pm, category, null);
    }

    public List<Board> getBoards(PersistenceManager pm, Category category, String filterKey, String filterValue) {
        Map<String, Object> filterMap = new HashMap<String, Object>(1);
        filterMap.put(filterKey, filterValue);
        return this.getBoards(pm, category, filterMap);
    }

    @SuppressWarnings("unchecked")
    public List<Board> getBoards(PersistenceManager pm, Category category, Map<String, Object> filterMap) {
        QueryImpl q = new QueryImpl(pm, Board.class);
        q.setFilter("category == board_category && (totDoc == tot_doc || totDoc == tot_doc.masterTotDoc)");
        q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.Category board_category");
        q.setSearchFilter(filterMap);
        q.setOrdering("id desc");

        return (List<Board>) q.execute(this, category);
    }





    public List<TotReport> getAllReports(PersistenceManager pm, boolean recursive) {
        return this.getAllReports(pm, null, recursive);
    }

    public List<TotReport> getAllReports(PersistenceManager pm, String filterKey, Object filterValue) {
        return this.getAllReports(pm, filterKey, filterValue, DEFAULT_REPORT_RECURSION);
    }

    public List<TotReport> getAllReports(PersistenceManager pm, String filterKey, Object filterValue, boolean recursive) {
        Map<String, Object> filterMap = new HashMap<String, Object>(1);
        filterMap.put(filterKey, filterValue);
        return this.getAllReports(pm, filterMap, recursive);
    }

    public List<TotReport> getAllReports(PersistenceManager pm, Map<String, Object> filterMap) {
        return this.getAllReports(pm, filterMap, DEFAULT_REPORT_RECURSION);
    }

    public List<TotReport> getSortOrgReports(PersistenceManager pm) {
        return this.getSortOrgReports(pm, null, DEFAULT_REPORT_RECURSION);
    }

    @SuppressWarnings("unchecked")
    public List<TotReport> getSortOrgReports(PersistenceManager pm, Map<String, Object> filterMap, boolean recursive) {
        QueryImpl q = new QueryImpl(pm, TotReport.class);

        q.setFilter("totDoc == tot_doc && isDeleted == 'N'");
        q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
        q.setSearchFilter(filterMap);
        q.setOrdering("mDept.organ ASC, mDept.upperDept, mDept.grade ASC,mDept.foundation ASC, mDept.name ASC");

        //System.out.println(QueryImpl.SQL);

        List<TotReport> reportList = (List<TotReport>) q.execute(this);
        return recursive ? this.getRecursiveAllReports(pm, reportList, filterMap) : reportList;
    }

    public List<TotReport> getSortSchReports(PersistenceManager pm) {
        return this.getSortSchReports(pm, null, DEFAULT_REPORT_RECURSION);
    }

    @SuppressWarnings("unchecked")
    public List<TotReport> getSortSchReports(PersistenceManager pm, Map<String, Object> filterMap, boolean recursive) {
        QueryImpl q = new QueryImpl(pm, TotReport.class);

        q.setFilter("totDoc == tot_doc && isDeleted == 'N'");
        q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
        q.setSearchFilter(filterMap);
        q.setOrdering("mDept.grade ASC,mDept.foundation ASC, mDept.organ ASC, mDept.upperDept, mDept.name ASC");

        //System.out.println(QueryImpl.SQL);

        List<TotReport> reportList = (List<TotReport>) q.execute(this);
        return recursive ? this.getRecursiveAllReports(pm, reportList, filterMap) : reportList;
    }


    public List<TotReport> getAllReports(PersistenceManager pm) {
        return this.getAllReports(pm, null, DEFAULT_REPORT_RECURSION);
    }

    @SuppressWarnings("unchecked")
    public List<TotReport> getAllReports(PersistenceManager pm, Map<String, Object> filterMap, boolean recursive) {
        QueryImpl q = new QueryImpl(pm, TotReport.class);

        q.setFilter("totDoc == tot_doc && isDeleted == 'N'");
        q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
        q.setSearchFilter(filterMap);
        q.setOrdering("  mDept.grade ASC, mDept.foundation ASC, mDept.organ ASC, mDept.upperDept, mDept.name ASC");

        //System.out.println("totDoc java getAllReports:::::쿼리:::::"+QueryImpl.SQL);

        List<TotReport> reportList = (List<TotReport>) q.execute(this);
        return recursive ? this.getRecursiveAllReports(pm, reportList, filterMap) : reportList;
    }

    public List<TotReport> getSortReports2(PersistenceManager pm,String key,String value) {
        return this.getSortReports2(pm, key,value, DEFAULT_REPORT_RECURSION);
    }

    @SuppressWarnings("unchecked")
    public List<TotReport> getSortReports2(PersistenceManager pm,String key,String value, boolean recursive)
    {
        List tmpList=null;
        StringBuilder filter = new StringBuilder();
        QueryImpl q = new QueryImpl(pm, TotReport.class);
        List<TotReport> reportList=null;
        filter.append("totDoc == tot_doc && isDeleted == 'N'");
        q.setFilter(filter.toString());
        q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
        q.setOrdering("mDept.grade ASC,mDept.foundation ASC,mDept.organ ASC,mDept.upperDept DESC,mDept.name ASC");
        reportList=(List<TotReport>) q.execute(this);
        reportList=this.getRecursiveAllReports(pm, reportList, null);
        List<TotReport> reportList2=new ArrayList<TotReport>();
        if(value!=null && !value.equals(""))
        {
            for(TotReport report:reportList)
            {
                String tmp1=report.getDept(pm).getName();
                String tmp2=report.getDept(pm).getOrgan(pm).getName();
                String tmp3=report.getOwnerName(pm);
                if(tmp1!=null && tmp1.indexOf(value)>=0) { reportList2.add(report); continue; }
                if(tmp2!=null && tmp2.indexOf(value)>=0) { reportList2.add(report); continue; }
                if(tmp3!=null && tmp3.indexOf(value)>=0) { reportList2.add(report); continue; }
            }
            return reportList2;
        }
        else return reportList;
    }

    public List<TotReport> getAllReports2(PersistenceManager pm,String key,String value) {
        return this.getAllReports2(pm, key,value, DEFAULT_REPORT_RECURSION);
    }

    @SuppressWarnings("unchecked")
    public List<TotReport> getAllReports2(PersistenceManager pm,String key,String value, boolean recursive)
    {
        List tmpList=null;
        StringBuilder filter = new StringBuilder();
        QueryImpl q = new QueryImpl(pm, TotReport.class);
        List<TotReport> reportList=null;
        filter.append("totDoc == tot_doc && isDeleted == 'N'");
        q.setFilter(filter.toString());
        q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
        q.setOrdering("mDept.organ ASC,mDept.upperDept,mDept.grade ASC,mDept.foundation ASC, mDept.name ASC");
        reportList=(List<TotReport>) q.execute(this);
        reportList=this.getRecursiveAllReports(pm, reportList, null);
        List<TotReport> reportList2=new ArrayList<TotReport>();
        if(value!=null && !value.equals(""))
        {
            for(TotReport report:reportList)
            {
                String tmp1=report.getDept(pm).getName();
                String tmp2=report.getDept(pm).getOrgan(pm).getName();
                String tmp3=report.getOwnerName(pm);
                if(tmp1!=null && tmp1.indexOf(value)>=0) { reportList2.add(report); continue; }
                if(tmp2!=null && tmp2.indexOf(value)>=0) { reportList2.add(report); continue; }
                if(tmp3!=null && tmp3.indexOf(value)>=0) { reportList2.add(report); continue; }
            }
            return reportList2;
        }
        else return reportList;
    }

    public List<TotReport> getPrssReports(PersistenceManager pm, int listType, String filterKey, Object filterValue,String howSort) {
        return getPrssReports(pm, TotReportProcess.values()[listType], filterKey, filterValue, howSort);
    }

    @SuppressWarnings("unchecked")
    public List<TotReport> getPrssReports(PersistenceManager pm, TotReportProcess process, String filterKey,Object filterValue,String howSort) {

        //45.semicolon 사용 오류(CWE-483) Update by YOUNGJUN,CHO
        String ordering = "mDept.organ ASC, mDept.upperDept, mDept.grade, mDept.foundation ASC, mDept.name ASC";
        if(howSort == null || howSort.equals("")) {
            ordering="mDept.organ ASC, mDept.upperDept, mDept.grade, mDept.foundation ASC, mDept.name ASC";
        }else{
        	ordering = howSort;
        }
        List tmpList=null;

        QueryImpl q = new QueryImpl(pm, TotReport.class);

        StringBuilder filter = new StringBuilder();
        filter.append("totDoc == tot_doc && isDeleted == 'N'");

        if(process == TotReportProcess.NOT_REPORT) {
            filter.append(" && process.ordinal() < TotReportProcess.COMP.ordinal()");
        } else if(process == TotReportProcess.ALL) {
            // do nothing.
            filter.append("");
        } else {
            if(process == TotReportProcess.COMP) {
                filter.append(" && process == prss ");
            } else if(process == TotReportProcess.NOTE) {
                filter.append(" && process == prss ");
            } else {
                filter.append(" && process == prss");
            }
        }

        /*
        if (filterKey.equals("mDept.name")) {
            tmpList=getSearchDept(pm,filterValue);
            filter.append(" && tmpList.contains(mDept)");
            //filter.append(" && mDept.contains(tmpList)");
        }
        */

        if(howSort!=null && !howSort.equals("")) {
            filter.append("&& submitDate != null");
        }

        q.setFilter(filter.toString());
        q.setOrdering(ordering);

        if(process != TotReportProcess.ALL && process != TotReportProcess.NOT_REPORT) {
            /*
            if(filterKey.equals("mDept.name")) {
                q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.TotReportProcess prss,java.util.List tmpList");
                return (List<TotReport>) q.execute(this, process,tmpList);
            }
            */
            q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.TotReportProcess prss");
            //v2. 6.SQL 삽입 : DO형식이므로 해결책에 따른 prepare SQL 문으로 변경할 수 없음
            return (List<TotReport>) q.execute(this, process);
            //================
        } else {
            /*
            if(filterKey.equals("mDept.name")) {
                q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc,java.util.List tmpList");
                return (List<TotReport>) q.execute(this,tmpList);
            }
            */
            q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
            return (List<TotReport>) q.execute(this);
        }
        //================================================
    }

    public List<TotReport> getPrssFoundReports(PersistenceManager pm, int listType, String filterKey, Object filterValue,String howSort) {
        return getPrssFoundReports(pm, TotReportProcess.values()[listType], filterKey, filterValue, howSort);
    }

    @SuppressWarnings("unchecked")
    public List<TotReport> getPrssFoundReports(PersistenceManager pm, TotReportProcess process, String filterKey,Object filterValue,String howSort) {
        //System.out.println("getPrssFoundReports:::::타기");
        //45.semicolon 사용 오류(CWE-483) Update by YOUNGJUN,CHO
        String ordering="mDept.grade,mDept.foundation ASC,mDept.organ ASC,mDept.upperDept,mDept.name ASC";
        if(howSort==null || howSort.equals("")) {
            ordering="mDept.grade,mDept.foundation ASC,mDept.organ ASC,mDept.upperDept,mDept.name ASC";
        } else {
            ordering=howSort;
        }
        List tmpList=null;

        QueryImpl q = new QueryImpl(pm, TotReport.class);

        StringBuilder filter = new StringBuilder();
        filter.append("totDoc==tot_doc && isDeleted == 'N'");

        if(process==TotReportProcess.NOT_REPORT) {
            filter.append(" && process.ordinal()<TotReportProcess.COMP.ordinal()");
        } else if(process == TotReportProcess.ALL) {
            // do nothing.
            filter.append("");
        } else {
            if(process==TotReportProcess.COMP) {
                filter.append(" && process==prss ");
            } else if( process==TotReportProcess.NOTE) {
                filter.append(" && process==prss ");
            } else {
                filter.append(" && process==prss");
            }
        }
        /*
        if (filterKey.equals("mDept.name")) {
            tmpList=getSearchDept(pm,filterValue);
            filter.append(" && tmpList.contains(mDept)");
            //filter.append(" && mDept.contains(tmpList)");
	}
        */
        if(howSort!=null && !howSort.equals("")) {
            filter.append("&& submitDate != null");
        }

        q.setFilter(filter.toString());
        q.setOrdering(ordering);

        if(process != TotReportProcess.ALL && process != TotReportProcess.NOT_REPORT) {
            /*
            if(filterKey.equals("mDept.name")) {
                q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.TotReportProcess prss,java.util.List tmpList");
                return (List<TotReport>) q.execute(this, process,tmpList);
            }
            */
            q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.TotReportProcess prss");
            //v2. 6.SQL 삽입 : DO형식이므로 해결책에 따른 prepare SQL 문으로 변경할 수 없음
            return (List<TotReport>) q.execute(this, process);
            //================
        } else {
            /*
            if(filterKey.equals("mDept.name")) {
                q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc,java.util.List tmpList");
                return (List<TotReport>) q.execute(this,tmpList);
            }
            */
            q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
            return (List<TotReport>) q.execute(this);
        }
        //================================================
    }

    //설립일 정렬 2012.10.16일 추가
    public List<TotReport> getFoundationFoundReports(PersistenceManager pm, int listType, String filterKey, Object filterValue,String howSort) {
        return getFoundationFoundReports(pm, TotReportProcess.values()[listType], filterKey, filterValue, howSort);
    }

    public List<TotReport> getFoundationFoundReports(PersistenceManager pm, TotReportProcess process, String filterKey,Object filterValue,String howSort) {
        //System.out.println("getFoundationFoundReports:::::타기");

        //45.semicolon 사용 오류(CWE-483) Update by YOUNGJUN,CHO
        String ordering="mDept.grade,mDept.foundation ASC,mDept.organ ASC,mDept.upperDept,mDept.name ASC";
        if(howSort==null || howSort.equals("")) {
            ordering="mDept.grade,mDept.foundation ASC,mDept.organ ASC,mDept.upperDept,mDept.name ASC";
        } else {
            ordering=howSort;
        }

        List tmpList=null;

        QueryImpl q = new QueryImpl(pm, TotReport.class);

        StringBuilder filter = new StringBuilder();
        filter.append("totDoc==tot_doc && isDeleted == 'N'");

        if(process==TotReportProcess.NOT_REPORT) {
            filter.append(" && process.ordinal()<TotReportProcess.COMP.ordinal()");
        } else if(process == TotReportProcess.ALL) {
            // do nothing.
            filter.append("");
        } else {
            if(process==TotReportProcess.COMP) {
                filter.append(" && process==prss ");
            } else if( process==TotReportProcess.NOTE) {
                filter.append(" && process==prss ");
            } else {
                filter.append(" && process==prss");
            }
        }

        if(howSort!=null && !howSort.equals("")) {
            filter.append("&& submitDate != null");
        }

        q.setFilter(filter.toString());
        q.setOrdering(ordering);

        if(process != TotReportProcess.ALL && process != TotReportProcess.NOT_REPORT) {
            /*
            if(filterKey.equals("mDept.name")) {
                q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.TotReportProcess prss,java.util.List tmpList");
                return (List<TotReport>) q.execute(this, process,tmpList);
            }
            */
            q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.TotReportProcess prss");
            //v2. 6.SQL 삽입 : DO형식이므로 해결책에 따른 prepare SQL 문으로 변경할 수 없음
            return (List<TotReport>) q.execute(this, process);
            //================
        } else {
            /*
            if(filterKey.equals("mDept.name")) {
                q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc,java.util.List tmpList");
                return (List<TotReport>) q.execute(this,tmpList);
            }
            */
            q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
            return (List<TotReport>) q.execute(this);
        }
        //================================================
    }

    public List<TotReport2> getPrssReports2(PersistenceManager pm, int listType, String filterKey, Object filterValue,String howSort) {
        return getPrssReports2(pm, TotReportProcess.values()[listType], filterKey, filterValue, howSort);
    }

    @SuppressWarnings("unchecked")
    public List<TotReport2> getPrssReports2(PersistenceManager pm, TotReportProcess process, String filterKey,Object filterValue,String howSort) {

        String ordering="mDept.organ, mDept.upperDept, mDept.grade, mDept.foundation,mDept.name ASC";

        if(howSort==null || howSort.equals("")) {
            ordering="mDept.organ, mDept.upperDept, mDept.grade,mDept.foundation,mDept.name ASC";
        } else {
            ordering=howSort;
        }

        List tmpList=null;
        QueryImpl q = new QueryImpl(pm, TotReport2.class);

        StringBuilder filter = new StringBuilder();
        filter.append("totDoc==tot_doc && isDeleted == 'N'");

        //45.semicolon 사용 오류(CWE-483) Update by YOUNGJUN,CHO
        //if(process==TotReportProcess.NOT_REPORT) filter.append(" && process.ordinal()<TotReportProcess.COMP.ordinal()");
	//			else if(process == TotReportProcess.ALL);
	//			else filter.append(" && process==prss");
        if(process==TotReportProcess.NOT_REPORT) {
            filter.append(" && process.ordinal()<TotReportProcess.COMP.ordinal()");
        } else if(process == TotReportProcess.ALL) {
            // do nothing.
            filter.append("");
        } else {
            filter.append(" && process==prss");
        }

        if (filterKey.equals("mDept.name")) {
            filter.append(" && mDept.name.contains(searchWord)");
        }

	if(howSort!=null && !howSort.equals("")) {
            filter.append("&& submitDate != null");
        }
        //================================================

        q.setFilter(filter.toString());
        q.setOrdering(ordering);

        if(process != TotReportProcess.ALL && process != TotReportProcess.NOT_REPORT) {
            if(filterKey.equals("mDept.name")) {
                q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.TotReportProcess prss,String searchWord");
                //v2. 6.SQL 삽입 : DO형식이므로 해결책에 따른 prepare SQL 문으로 변경할 수 없음
                return (List<TotReport2>) q.execute(this, process,tmpList);
                //===============
            }

            q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.TotReportProcess prss");
            //v2. 6.SQL 삽입 : DO형식이므로 해결책에 따른 prepare SQL 문으로 변경할 수 없음
            return (List<TotReport2>) q.execute(this, process);
            //===============
        } else {
            if(filterKey.equals("mDept.name")) {
                q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc,String searchWord");
                return (List<TotReport2>) q.execute(this,tmpList);
            }

            q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
            return (List<TotReport2>) q.execute(this);
	}
    }

   /*******************************************************************************************************************************
    @SuppressWarnings("unchecked")
    public List<TotReport> getPrssReports(PersistenceManager pm, TotReportProcess process, String filterKey,Object filterValue)
		{
        QueryImpl q = new QueryImpl(pm, TotReport.class);
        StringBuilder filter = new StringBuilder();
        filter.append("totDoc==tot_doc && isDeleted==false");
        if(process==TotReportProcess.NOT_REPORT) filter.append(" && process.ordinal()<TotReportProcess.COMP.ordinal()");
				else if(process == TotReportProcess.ALL);
				else filter.append(" && process==prss");
        if (filterKey.equals("mDept.name"))
				{
					List tmpList=getSearchDept(pm,filterValue);
					if(tmpList.size()>0)
					{
          	filter.append("&& (");
						for(int ii=0;ii<tmpList.size();ii++)
          	{
							if(ii==0) filter.append("mDept==\""+tmpList.get(ii)+"\"");
							else filter.append("||mDept==\""+tmpList.get(ii)+"\"");
          	}
						filter.append(")");
					}
				}
				q.setFilter(filter.toString());
                q.setOrdering("mDept ASC");
				LOG.debug("******************************************************************************* filter {}", filter.toString());
				LOG.debug("******************************************************************************* filterKey: {}",filterKey);
				LOG.debug("******************************************************************************* filterValue: {}",filterValue);
				LOG.debug("******************************************************************************* tmpList: {}",tmpList);
        if(process != TotReportProcess.ALL && process != TotReportProcess.NOT_REPORT)
				{
          q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc, kr.co.kihyun.beans.entity.TotReportProcess prss");
          return (List<TotReport>) q.execute(this, process);
        }
				else
				{
					q.declareParameters("kr.co.kihyun.beans.entity.TotDoc tot_doc");
					return (List<TotReport>) q.execute(this);
				}
		}
*******************************************************************************************************************************/

		public List<String> getSearchDept(PersistenceManager pm, Object searchVal)
		{
			try
			{
              //System.out.println("SELECT id FROM moumi_Dept WHERE name like '%"+searchVal+"%'");
				Query q=pm.newQuery("javax.jdo.query.SQL","SELECT id||organ||upper_dept FROM moumi_Dept WHERE name like '%"+searchVal+"%'");
                    //v2. 6.SQL 삽입 : DO형식이므로 해결책에 따른 prepare SQL 문으로 변경할 수 없음
     		    return (List <String>) q.execute();
                    //================
			}
			catch(Exception ex)
			{
				ex.printStackTrace();
				throw new UnsupportedOperationException("Error! Error!");
			}
		}

    public List<TotReport> getCompReports(PersistenceManager pm) {
        return this.getCompReports(pm, null, null);
    }

    public List<TotReport> getCompReports(PersistenceManager pm, String filterKey, Object filterValue) {
        Map<String, Object> filterMap = new HashMap<String, Object>(1);
        filterMap.put(filterKey, filterValue);
        return this.getCompReports(pm, filterMap);
    }

    public List<TotReport> getCompReports(PersistenceManager pm, Map<String, Object> filterMap) {
        return this.getAcceptanceLimitStrategy().getCompReports(pm, filterMap);
    }

    public List<TotReport> getRecursiveAllReports(PersistenceManager pm, List<TotReport> reportList,
            Map<String, Object> filterMap) {
        List<TotReport> resultReportList = new ArrayList<TotReport>();
        for (TotReport report : reportList) {
            if (report.getSlaveTotDoc() == null) {
                resultReportList.add(report);
                //LOG.debug("{} added.", report);
            } else {
                List<TotReport> slaveReportList = report.getSlaveTotDoc().getAllReports(pm, filterMap, false);
                resultReportList.addAll(getRecursiveAllReports(pm, slaveReportList, filterMap));
            }
        }
        return resultReportList;
    }

    public List<TotReport> getRecursivePrssReports(PersistenceManager pm, List<TotReport> reportList,
            Map<String, Object> filterMap) {
        List<TotReport> resultReportList = new ArrayList<TotReport>();
        for (TotReport report : reportList) {
            if (report.getSlaveTotDoc() == null) {
                resultReportList.add(report);
                //LOG.debug("{} added.", report);
            } else {
                List<TotReport> slaveReportList = report.getSlaveTotDoc().getPrssReports(pm, TotReportProcess.COMP, "", null,null);
                resultReportList.addAll(getRecursiveAllReports(pm, slaveReportList, filterMap));
            }
        }
        return resultReportList;
    }

    @Override
	public MDept getOwnerParty(PersistenceManager pm) {
        return this.getDept(pm).getRootDept(pm);
    }

}
