package open.dolphin.session; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.GregorianCalendar; import java.util.Iterator; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.Stateless; import javax.inject.Named; import javax.persistence.EntityExistsException; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import open.dolphin.infomodel.*; import open.dolphin.msg.OidSender; import open.stamp.seed.CopyStampTreeBuilder; import open.stamp.seed.CopyStampTreeDirector; //import org.jboss.ejb3.annotation.ResourceAdapter; /** * * @author kazushi, Minagawa, Digital Globe, Inc. */ @Named @Stateless //s.oh^ 2014/02/21 Claim送信方法の変更 //@ResourceAdapter("hornetq-ra.rar") //s.oh$ public class SystemServiceBean { //private static final boolean DolphinPro = true; //private static final String BASE_OID = "1.3.6.1.4.1.9414.3."; // 3.xx //private static final String DEMO_FACILITY_ID = "1.3.6.1.4.1.9414.2.1"; private static final String BASE_OID = "1.3.6.1.4.1.9414.72."; private static final String DEMO_FACILITY_ID = "1.3.6.1.4.1.9414.70.1"; //70.1 private static final String QUERY_NEXT_FID = "select nextval('facility_num') as n"; private static final String QUERY_FACILITY_BY_FID = "from FacilityModel f where f.facilityId=:fid"; private static final String FID = "fid"; private static final String PK = "pk"; private static final String ASP_TESTER = "ASP_TESTER"; private static final int MAX_DEMO_PATIENTS = 5; private static final String ID_PREFIX = "D_"; private static final String QUERY_PATIENT_BY_FID = "from PatientModel p where p.facilityId=:fid order by p.patientId"; private static final String QUERY_HEALTH_INSURANCE_BY_PATIENT_PK = "from HealthInsuranceModel h where h.patient.id=:pk"; private static final String TREE_SOURCE = "1.3.6.1.4.1.9414.70.1:admin"; ////"1.3.6.1.4.1.9414.70.1:lsc_admin" @PersistenceContext private EntityManager em; //s.oh^ 2014/02/21 Claim送信方法の変更 //@Resource(mappedName = "java:/JmsXA") //private ConnectionFactory connectionFactory; // //@Resource(mappedName = "java:/queue/dolphin") //private javax.jms.Queue queue; //s.oh$ /** * 施設と管理者情報を登録する。 * * @param user 施設管理者 */ public AccountSummary addFacilityAdmin(UserModel user) { // シーケンサから次の施設番号を得る java.math.BigInteger nextId = (java.math.BigInteger)em.createNativeQuery(QUERY_NEXT_FID).getSingleResult(); Long nextFnum = new Long(nextId.longValue()); // 施設OIDを生成する base.next StringBuilder sb = new StringBuilder(); sb.append(BASE_OID).append(String.valueOf(nextFnum)); String fid = sb.toString(); // OIDをセットし施設レコードを生成する FacilityModel facility = user.getFacilityModel(); facility.setFacilityId(fid); try { em.createQuery(QUERY_FACILITY_BY_FID) .setParameter(FID, fid) .getSingleResult(); // すでに存在している場合は例外をスローする throw new EntityExistsException(); } catch (NoResultException e) { // 当たり前 } // Persist the Facility // このメソッドで facility が管理された状態になる em.persist(facility); // userId=fid:uid sb = new StringBuilder(); sb.append(fid); sb.append(IInfoModel.COMPOSITE_KEY_MAKER); sb.append(user.getUserId()); user.setUserId(sb.toString()); // role Collection<RoleModel> roles = user.getRoles(); if (roles != null) { for (RoleModel role : roles) { role.setUserModel(user); role.setUserId(user.getUserId()); } } // Persist the User // Role には User から CascadeType.ALL が設定されている em.persist(user); //----------------------------------- // 評価ユーザなのでデモ用の患者を生成する //----------------------------------- Collection demoPatients = em.createQuery(QUERY_PATIENT_BY_FID) .setParameter(FID, DEMO_FACILITY_ID) .setFirstResult(1) .setMaxResults(MAX_DEMO_PATIENTS) .getResultList(); for (Iterator iter = demoPatients.iterator(); iter.hasNext(); ) { PatientModel demoPatient = (PatientModel) iter.next(); PatientModel copyPatient = new PatientModel(); copyPatient.setFacilityId(fid); copyPatient.setPatientId(ID_PREFIX + demoPatient.getPatientId()); // D_0001 ec copyPatient.setFamilyName(demoPatient.getFamilyName()); copyPatient.setGivenName(demoPatient.getGivenName()); copyPatient.setFullName(demoPatient.getFullName()); copyPatient.setKanaFamilyName(demoPatient.getKanaFamilyName()); copyPatient.setKanaGivenName(demoPatient.getKanaGivenName()); copyPatient.setKanaName(demoPatient.getKanaName()); copyPatient.setGender(demoPatient.getGender()); copyPatient.setGenderDesc(demoPatient.getGenderDesc()); copyPatient.setBirthday(demoPatient.getBirthday()); copyPatient.setSimpleAddressModel(demoPatient.getSimpleAddressModel()); copyPatient.setTelephone(demoPatient.getTelephone()); // 健康保険を設定する Collection demoInsurances = em.createQuery(QUERY_HEALTH_INSURANCE_BY_PATIENT_PK) .setParameter(PK, demoPatient.getId()).getResultList(); for (Iterator iter2 = demoInsurances.iterator(); iter2.hasNext(); ) { HealthInsuranceModel demoInsurance = (HealthInsuranceModel) iter2.next(); HealthInsuranceModel copyInsurance = new HealthInsuranceModel(); copyInsurance.setBeanBytes(demoInsurance.getBeanBytes()); copyInsurance.setPatient(copyPatient); copyPatient.addHealthInsurance(copyInsurance); } // 永続化する em.persist(copyPatient); // カルテを生成する KarteBean karte = new KarteBean(); karte.setPatientModel(copyPatient); karte.setCreated(new Date()); em.persist(karte); } //---------------------------------------- // StampTreeを生成する //---------------------------------------- try { // admin の StampTreeModel を取得する UserModel admin = (UserModel) em.createQuery("from UserModel u where u.userId=:uid") .setParameter("uid", TREE_SOURCE) .getSingleResult(); List<StampTreeModel> list = (List<StampTreeModel>) em.createQuery("from StampTreeModel s where s.user.id=:userPK") .setParameter("userPK", admin.getId()) .getResultList(); StampTreeModel st = list.remove(0); // 上記StampTreeModelのtreeXmlをコピーする InputStream is = new ByteArrayInputStream(st.getTreeBytes()); BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8")); CopyStampTreeBuilder builder = new CopyStampTreeBuilder(); CopyStampTreeDirector director = new CopyStampTreeDirector(builder); director.build(br); br.close(); // copyした treeXml & bytes String copiedTreeXml = builder.getStampTreeXML(); byte[] treeBytes = copiedTreeXml.getBytes("UTF-8"); // copyした treeXml を登録ユーザーのTreeとして永続化する StampTreeModel copyTree = new StampTreeModel(); copyTree.setTreeBytes(treeBytes); copyTree.setUserModel(user); copyTree.setName("個人用"); copyTree.setDescription("個人用のスタンプセットです"); copyTree.setPartyName(user.getFacilityModel().getFacilityName()); if (user.getFacilityModel().getUrl()!=null) { copyTree.setUrl(user.getFacilityModel().getUrl()); } em.persist(copyTree); // copy Treeに関連づけされているStampの実態を永続化する List<StampModel> stampToPersist = builder.getStampModelToPersist(); List<String> seedStampIdList = builder.getSeedStampList(); for (int i=0; i<stampToPersist.size();i++) { String id = seedStampIdList.get(i); StampModel seed = (StampModel)em.find(StampModel.class, id); StampModel persist = stampToPersist.get(i); persist.setStampBytes(seed.getStampBytes()); persist.setUserId(user.getId()); em.persist(persist); } } catch (Exception e) { e.printStackTrace(System.err); } AccountSummary account = new AccountSummary(); account.setMemberType(ASP_TESTER); account.setFacilityAddress(user.getFacilityModel().getAddress()); account.setFacilityId(user.getFacilityModel().getFacilityId()); account.setFacilityName(user.getFacilityModel().getFacilityName()); account.setFacilityTelephone(user.getFacilityModel().getTelephone()); account.setFacilityZipCode(user.getFacilityModel().getZipCode()); account.setUserEmail(user.getEmail()); account.setUserName(user.getCommonName()); account.setUserId(user.idAsLocal()); return account; } //s.oh^ 2014/07/08 クラウド0対応 /** * カルテ枚数等、全件数をカウントする * @param fid 医療機関 OID * @return */ public ActivityModel countTotalActivities(String fid) { ActivityModel am = new ActivityModel(); // ユーザー数 StringBuilder sb = new StringBuilder(); sb.append("select count(u.id) from UserModel u where u.userId like :fid and u.memberType!=:memberType"); String sql = sb.toString(); Object obj = em.createQuery(sql) .setParameter("fid", fid+":%") .setParameter("memberType", "EXPIRED") .getSingleResult(); long count = (long)obj; am.setNumOfUsers(count); // 全患者数 sb = new StringBuilder(); sb.append("select count(p.id) from PatientModel p where p.facilityId=:fid"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid) .getSingleResult(); count = (long)obj; am.setNumOfPatients(count); // 延べ来院患者 sb = new StringBuilder(); sb.append("select count(p.id) from PatientVisitModel p where p.facilityId=:fid and p.status!=:status"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid) .setParameter("status", 6) .getSingleResult(); count = (long)obj; am.setNumOfPatientVisits(count); // 全カルテ数 sb = new StringBuilder(); sb.append("select count(d.id) from DocumentModel d where d.creator.userId like :fid and d.status='F'"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .getSingleResult(); count = (long)obj; am.setNumOfKarte(count); // 全画像数 sb = new StringBuilder(); sb.append("select count(s.id) from SchemaModel s where s.creator.userId like :fid and s.status='F'"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .getSingleResult(); count = (long)obj; am.setNumOfImages(count); // 添付文書数 sb = new StringBuilder(); sb.append("select count(a.id) from AttachmentModel a where a.creator.userId like :fid and a.status='F'"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .getSingleResult(); count = (long)obj; am.setNumOfAttachments(count); // 病名数 RegisteredDiagnosisModel sb = new StringBuilder(); sb.append("select count(r.id) from RegisteredDiagnosisModel r where r.creator.userId like :fid"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .getSingleResult(); count = (long)obj; am.setNumOfDiagnosis(count); // 紹介状数 sb = new StringBuilder(); sb.append("select count(l.id) from LetterModule l where l.creator.userId like :fid and l.status='F'"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .getSingleResult(); count = (long)obj; am.setNumOfLetters(count); // 検査数 sb = new StringBuilder(); sb.append("select count(l.id) from NLaboModule l where l.patientId like :fid"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .getSingleResult(); count = (long)obj; am.setNumOfLabTests(count); // 医療機関情報 sb = new StringBuilder(); sb.append("from FacilityModel f where f.facilityId=:fid"); sql = sb.toString(); FacilityModel fm = (FacilityModel)em.createQuery(sql) .setParameter("fid", fid) .getSingleResult(); am.setFacilityId(fm.getFacilityId()); am.setFacilityName(fm.getFacilityName()); am.setFacilityZip(fm.getZipCode()); am.setFacilityAddress(fm.getAddress()); am.setFacilityTelephone(fm.getTelephone()); am.setFacilityFacimile(fm.getFacsimile()); // DB size sb = new StringBuilder(); sb.append("select pg_size_pretty(pg_database_size('dolphin'))"); sql = sb.toString(); obj = em.createNativeQuery(sql).getSingleResult(); am.setDbSize(obj.toString()); // bind address am.setBindAddress(this.getBindAddress()); return am; } /** * 対象期間のレコード件数をカウントする * @param fid 医療機関OID * @param from 集計開始日 * @param to 集計終了日 * @return */ public ActivityModel countActivities(String fid, Date from, Date to) { ActivityModel am = new ActivityModel(); am.setFromDate(from); am.setToDate(to); // 対象期間の新規患者 StringBuilder sb = new StringBuilder(); sb.append("select count(p.id) from PatientModel p, KarteBean k where p.id=k.patient.id and p.facilityId=:fid and k.created between :fromDate and :toDate"); String sql = sb.toString(); Object obj = em.createQuery(sql) .setParameter("fid", fid) .setParameter("fromDate", from) .setParameter("toDate", to) .getSingleResult(); long count = (long)obj; am.setNumOfPatients(count); // 対象期間の来院数 sb = new StringBuilder(); sb.append("select count(p.id) from PatientVisitModel p where p.facilityId=:fid and p.pvtDate between :fromDate and :toDate and p.status!=:status"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid) .setParameter("fromDate", pvtDateFromDate(from)) .setParameter("toDate", pvtDateFromDate(to)) .setParameter("status", 6) .getSingleResult(); count = (long)obj; am.setNumOfPatientVisits(count); // 対象期間のカルテ枚数 sb = new StringBuilder(); sb.append("select count(d.id) from DocumentModel d where d.creator.userId like :fid and d.started between :fromDate and :toDate and d.status='F'"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .setParameter("fromDate", from) .setParameter("toDate", to) .getSingleResult(); count = (long)obj; am.setNumOfKarte(count); // 対象期間画像数 sb = new StringBuilder(); sb.append("select count(s.id) from SchemaModel s where s.creator.userId like :fid and s.started between :fromDate and :toDate and s.status='F'"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .setParameter("fromDate", from) .setParameter("toDate", to) .getSingleResult(); count = (long)obj; am.setNumOfImages(count); // 対象期間添付文書数 sb = new StringBuilder(); sb.append("select count(a.id) from AttachmentModel a where a.creator.userId like :fid and a.started between :fromDate and :toDate and a.status='F'"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .setParameter("fromDate", from) .setParameter("toDate", to) .getSingleResult(); count = (long)obj; am.setNumOfAttachments(count); // 対象期間病名数 sb = new StringBuilder(); sb.append("select count(r.id) from RegisteredDiagnosisModel r where r.creator.userId like :fid and r.started between :fromDate and :toDate"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .setParameter("fromDate", from) .setParameter("toDate", to) .getSingleResult(); count = (long)obj; am.setNumOfDiagnosis(count); // 対象期間の紹介状数 sb = new StringBuilder(); sb.append("select count(l.id) from LetterModule l where l.creator.userId like :fid and l.started between :fromDate and :toDate and l.status='F'"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .setParameter("fromDate", from) .setParameter("toDate", to) .getSingleResult(); count = (long)obj; am.setNumOfLetters(count); // 対象期間の検査数 sb = new StringBuilder(); sb.append("select count(l.id) from NLaboModule l where l.patientId like :fid and l.sampleDate between :fromDate and :toDate"); sql = sb.toString(); obj = em.createQuery(sql) .setParameter("fid", fid+":%") .setParameter("fromDate", sampleDateFromDate(from)) .setParameter("toDate", sampleDateFromDate(to)) .getSingleResult(); count = (long)obj; am.setNumOfLabTests(count); return am; } public void mailActivities(ActivityModel[] ams) { ActivityModel am = ams[0]; ActivityModel total = ams[1]; // log log("開始日時", am.getFromDate().toString()); log("終了日時", am.getToDate().toString()); log("医療機関ID", total.getFacilityId()); log("医療機関名", total.getFacilityName()); log("郵便番号", total.getFacilityZip()); log("住所", total.getFacilityAddress()); log("電話", total.getFacilityTelephone()); log("FAX", total.getFacilityFacimile()); log("利用者数", am.getNumOfUsers()); log("患者数", am.getNumOfPatients(), total.getNumOfPatients()); log("来院数", am.getNumOfPatientVisits(),total.getNumOfPatientVisits()); log("病名数", am.getNumOfDiagnosis(),total.getNumOfDiagnosis()); log("カルテ枚数", am.getNumOfKarte(),total.getNumOfKarte()); log("画像数", am.getNumOfImages(),total.getNumOfImages()); log("添付文書数", am.getNumOfAttachments(),total.getNumOfAttachments()); log("紹介状数", am.getNumOfLetters(),total.getNumOfLetters()); log("検査数", am.getNumOfLabTests(),total.getNumOfLabTests()); log("データベース容量", total.getDbSize()); log("IP アドレス", total.getBindAddress()); // MailでOIDを通知するためMessageDrivenBeanに渡す //Connection conn = null; //try { // conn = connectionFactory.createConnection(); // Session session = conn.createSession(false, QueueSession.AUTO_ACKNOWLEDGE); // ObjectMessage msg = session.createObjectMessage(ams); // MessageProducer producer = session.createProducer(queue); // producer.send(msg); // //} catch (JMSException e) { // e.printStackTrace(System.err); // throw new RuntimeException(e.getMessage()); // //} //finally { // if(conn != null) // { // try // { // conn.close(); // } // catch (JMSException e) // { // } // } //} Logger.getLogger("open.dolphin").info("ActivityModel message has received. Reporting will start(Not Que)."); OidSender sender = new OidSender(); try { sender.sendActivity(ams); } catch (Exception ex) { ex.printStackTrace(System.err); Logger.getLogger("open.dolphin").warning("ActivityModel message send error : " + ex.getMessage()); } } public void sendMonthlyActivities(int year, int month) { // 対象月の1日 GregorianCalendar gcFrom = new GregorianCalendar(year, month, 1); Date fromDate = gcFrom.getTime(); // 対象月の最後 GregorianCalendar gcTo = new GregorianCalendar(year, month, gcFrom.getActualMaximum(Calendar.DAY_OF_MONTH), 23, 59, 59); Date toDate = gcTo.getTime(); List<FacilityModel> list = (List<FacilityModel>)em.createQuery("from FacilityModel f").getResultList(); for (FacilityModel fm : list) { ActivityModel total = this.countTotalActivities(fm.getFacilityId()); total.setFlag("T"); ActivityModel target = this.countActivities(fm.getFacilityId(), fromDate, toDate); target.setFlag("M"); target.setFromDate(fromDate); target.setToDate(toDate); this.mailActivities(new ActivityModel[]{target, total}); } } private String pvtDateFromDate(Date d) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); return sdf.format(d); } private String sampleDateFromDate(Date d) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(d); } private String getBindAddress() { String test = System.getProperty("jboss.bind.address"); if (test==null) { try { InetAddress ip = InetAddress.getLocalHost(); if (ip!=null) { test = ip.toString(); } } catch (UnknownHostException ex) { Logger.getLogger("open.dolphin").log(Level.SEVERE, null, ex); } } return test; } private void log(String name, String value) { Logger.getLogger("open.dolphin").log(Level.INFO, "{0}={1}", new Object[]{name, value}); } private void log(String msg, long count) { Logger.getLogger("open.dolphin").log(Level.INFO, "{0}={1}", new Object[]{msg, count}); } private void log(String msg, long count, long total) { Logger.getLogger("open.dolphin").log(Level.INFO, "{0}={1}/{2}", new Object[]{msg, count, total}); } //s.oh$ }