ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [HL7/Fhir] plain server 기본 구동 원리 이해하기
    Framework/HL7 FHIR 2022. 6. 7. 22:45
    반응형

    HL7이란?

    HL7은 국제표준의료정보모델 규약이다. 의료정보 교류를 잘하기 위해서 만든 모델이며, 형식에 따라 필요한 정보를 표기한 다음 표현해주면 된다. 아래는 FHIR FRAMEWORK에서 사용하는 HL7을 표시해주는 사이트이다. 아래 사이트로 들어가 표현 하는 방식을 서칭한 다음 그 표시 형식대로 보내주거나 커스텀 하여 보내주면된다. 하는 방법은 다음 포스티에 설명 하겠다.

     

    Resourcelist - FHIR v4.3.0

     

    www.hl7.org

     

     

    FHIR Framework란?

    FHIR Framework란 HL7을 잘 표시해주기 위해 만든 웹 기반 프레임워크이다. 아래는 이 FHIR를 잘 구현하기 위해 만든 오픈 소스 프로젝트인 HAPI FHIR Framework 사이트이다. docs를 보고 구현하면 구현하기 편하다.

     

    Table of Contents - HAPI FHIR Documentation

    9.0.0 JPA Server: Partitioning and Multitenancy

    hapifhir.io

     

     

    FHIR Basic Architecture

    아래 이미지는 임의로 설계한 Architecture이며 HAPI FHIR에서 제공하는 공식 Architecture는 아님, FHIR는 spring-context, spring-annotation기반으로 구현이된 framework이기 때문에 MVC패턴과 유사한 모습을 보여주고 있음. 단지 명칭만 다르다는 것을 인지하면 쉽게 구현 가능

    FHIR Plain Server 구성요소

    • FhirContext - fhir버전을 등록하여 Context(버전 같은 것)를 등록
    • Model - HL7에 있는 Json형태를 쉽게 구현하기 위해 만들어 놓은 java class
    • Provider - Provider를 이용하여 api 호출에서 필요한 정보 정제 및 전달
    • Interceptor - Interceptor HTML을 그려주는 로직이 있는 곳

    FHIR 구동원리

    • Front에서 Back으로 정보 요청 - API 호출
    • AppContext에서 요청에 맞는 Provider를 찾아 해당 메소드 호출
    • Provider에서 관련 정보 DB에 호출
    • Provider는 필요한 정보에 맞게 Model을 구성하여 App-Context에 전달
    • AppContext는 해당 정보를 필요한 화면을 구성할 수 있게 Interceptor를 호출
    • Interceptor는 필요한 내용 HTML로 만들어 Client에 Response 해줌

    Main - FHIR 내부의 RestFulServer를 상속 받아서 실행 - AppContext를 나타냄

    @WebServlet("/*")
    public class ApplicationContext extends RestfulServer{
    
    	@Override
    	protected void initialize() throws ServletException {
    		try {
    			// FhirContext 로 버전 등록
    			setFhirContext(FhirContext.forR4());
    			
    			// Provider - 화면에 필요한 로직 구현 db접근 및 데이터 정재 Interceptor로 전달 
    			registerProvider(new His_patientProvider());
    			registerProvider(new His_grossProvider());
    			registerProvider(new His_wsiProvider());
    			
    			// Interceptor - Json 및 HTML 구현
    			registerInterceptor(new ResponseHighlighterInterceptor());
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    Model - HL7 fhir에 있는 model 들 재정의

    package ca.uhn.fhir.virtual_his.model; 
    
    import org.hl7.fhir.r4.model.QuestionnaireResponse;
    import org.hl7.fhir.r4.model.StringType;
    
    import ca.uhn.fhir.model.api.annotation.Child;
    import ca.uhn.fhir.model.api.annotation.Description;
    import ca.uhn.fhir.model.api.annotation.ResourceDef;
    import ca.uhn.fhir.util.ElementUtil;
    
    // @ResourceDef annotation은 - <http://~/hisgross로> 들어갈 수 있도록 구현
    @ResourceDef(name="hisgross")
    public class His_gross extends QuestionnaireResponse{
    
    	private static final long serialVersionUID = 2L;
    	
    	// fhir에서 child로 구성된 것중 정보가 안담긴것을 null로 화면에 안보여주게 해줌 꼭 설정해야 함
    	@Override
    	public boolean isEmpty() {
    		return super.isEmpty() && ElementUtil.isEmpty(pid, name, fileName);
    	}
    	
    	// @Child model 구성 요소로 정의 가능
    	@Child(name="pid")
    	@Description(shortDefinition="The pid of patient")
    	private StringType pid;
    	
    	@Child(name="name")
    	@Description(shortDefinition="The gross")
    	private StringType name;
    	
    	@Child(name="file_name")
    	@Description(shortDefinition="The file_name of gross")
    	private StringType fileName;
    	
    	// field getter 구성 
    	// StringType은 fhir에서 새로 정의되어 사용하는 String Class, IntType, IdType 등등 있음
    	public StringType getPid() {
    		if(pid == null) {
    			pid = new StringType();
    		}
    		return pid;
    	}
    	
    	public StringType getName() {
    		if(name == null) {
    			name = new StringType();
    		}
    		return name;
    	}
    	
    	public StringType getFileName() {
    		if(fileName == null) {
    			fileName = new StringType();
    		}
    		return fileName;
    	}
    	
    	// field setter 구성 
    	public void setPid(StringType inPid) {
    		pid = inPid;
    	}
    	
    	public void setName(StringType inName) {
    		name = inName;
    	}
    	
    	public void setFileName(StringType inFileName) {
    		fileName = inFileName;
    	}
    }
    

    Provider - url 요청에 따라 정보 response하는 역할

    package ca.uhn.fhir.virtual_his.provider;
    
    import java.sql.Connection;
    ...
    
    import org.hl7.fhir.instance.model.api.IBaseResource;
    import org.hl7.fhir.r4.model.IdType;
    import org.hl7.fhir.r4.model.StringType;
    
    import ca.uhn.fhir.rest.annotation.IdParam;
    ...
    
    public class His_grossProvider implements IResourceProvider{
        private String urlPath = "hisgross/";
    
        @Override
        public Class<? extends IBaseResource> getResourceType() {
            return His_gross.class;
        }
    
        // url 작성 방법 1
        // URL with grossId
        // prototype - hisgross/{id}
        // example   - hisgross/1
        @Read()
        public His_gross read(@IdParam IdType theId) {
            His_gross retVal = getGross(theId);
            if (retVal == null) {
                throw new ResourceNotFoundException(theId);
            }
            return retVal;
        }
    
        // url 작성 방법 2
        // 기본 URL
        // URL
        // example   - hisgross
        @Search
        public List<His_gross> search() {
            List<His_gross> retVal = getGrossList(null);
            if (retVal.size() <= 0) {
                throw new ResourceNotFoundException(new IdType(urlPath));
            }
            return retVal;
        }
    
        // url 작성 방법 3
        // _query로 query string url 구현 가능	
        // URL with namedQuery
        // prototype - hisgross?_query={QueryParamName}&{name}={value}
        // example   - hisgross?_query=withgrossname&grossid=pros_0001
        @Search(queryName="withgrossname")
        public List<His_gross> searchWithGrossName(@RequiredParam(name="grossname") StringParam grossName ) {
              List<His_gross> retVal = getGrossList(grossName.getValue());
              if (retVal.size() <= 0) {
                  throw new ResourceNotFoundException(new IdType(urlPath));
              }
              return retVal;
        }
    
        // url 작성 방법 3
        // URL with grossId
        // prototype - hisgross/{grossid}/$srh1?pid={pid}
        // example   - hisgross/pros_0001/$srh1?pid=P00000001
        @Operation(name="$srh1", idempotent=true)
        public His_gross PatientTypeOperation(@IdParam IdType theId,
                                              @OperationParam(name="pid") String pid) 
        {	
            String grossId = theId.toString().replace(urlPath, "");
            His_gross retVal = getGross(pid, grossId);
            if (retVal == null) {
                throw new ResourceNotFoundException(theId);
            }
            return retVal;
        }
    
        // url 작성 방법 4
        // URL without grossId
        // prototype - hisgross/$srh2?pid={pid}&grossid={grossid} 
        // example   - hisgross/$srh2?pid=P00000001&grossid=pros_0001 
        @Operation(name="$srh2", idempotent=true)
        public His_gross PatientTypeOperation(@OperationParam(name="pid") String pid,
                                              @OperationParam(name="grossid") String grossId) 
        {	
            His_gross retVal = getGross(pid, grossId);
            if (retVal == null) {
                throw new ResourceNotFoundException(new IdType(urlPath));
            }
            return retVal;
        }
    
        public His_gross getGross(IdType theId) {
            Connection con = null;
            DBBase ctxDB = null;
            ResultSet rs = null;
    
            His_gross his_gross = new His_gross();
            StringBuilder build_sql = new StringBuilder();
            String grossId = theId.toString().replace(urlPath, "");
    
            try {
                build_sql.append(" selecT * from his_gross ");
                build_sql.append("  where id='" + grossId + "'");
    
                ctxDB = new DBBase_mysql();
                con = ctxDB.DBConnector();
                rs = ctxDB.executeQuery(con, build_sql);
    
                // create gross json response
                while(rs.next()) {
                    his_gross.setId(theId);
                    his_gross.setPid(new StringType(rs.getString("pid")));
                    his_gross.setFileName(new StringType(rs.getString("file_name")));
                }
    
            }catch(SQLException ex) {  
                System.out.println("SQLException :" + ex.getMessage());
            }
    
            if(!his_gross.hasIdElement()) {
                throw new ResourceNotFoundException(theId);
            }
    
            return his_gross;
        }
    
        public List<His_gross> getGrossList(String grossName) {
            Connection con = null;
          DBBase ctxDB = null;
          ResultSet rs = null;
    
            List<His_gross> li_his_gross = new ArrayList<His_gross>();
            StringBuilder build_sql = new StringBuilder();
    
            try {
                // create a SQL
                // grossName에 따라 조회 되는 조건 설정 
                if(grossName == null) {
                    build_sql.append(" selecT * from his_gross limit 10");
                } else {
                    build_sql.append("selecT * from his_gross ");
                    build_sql.append(" where name ='" + grossName + "'");
                }
    
                ctxDB = new DBBase_mysql();
                con = ctxDB.DBConnector();
                rs = ctxDB.executeQuery(con, build_sql);
    
                // create gross messages
                while(rs.next()) {
                    His_gross his_gross = new His_gross();
                    his_gross.setId(new IdType(rs.getString("id")));
                    his_gross.setPid(new StringType(rs.getString("pid")));
                    his_gross.setFileName(new StringType(rs.getString("file_name")));
                    li_his_gross.add(his_gross);
                }
    
            }catch(SQLException ex) {  
                System.out.println("SQLException :" + ex.getMessage());
            }
    
            if(li_his_gross.size() <= 0 ) {
                throw new ResourceNotFoundException(new IdType(urlPath));
            }
            return li_his_gross;
        }
    
        public His_gross getGross(String pid, String grossId) {
          Connection con = null;
          DBBase ctxDB = null;
          ResultSet rs = null;
    
            His_gross his_gross = new His_gross();
            StringBuilder build_sql = new StringBuilder();
            IdType theId = new IdType(grossId);
    
            try {
                // create a SQL
                build_sql.append(" selecT * from his_gross ");
                build_sql.append("  where pid  ='" + pid + "'");
                build_sql.append("    and name ='" + grossId + "'");
    
                ctxDB = new DBBase_mysql();
                con = ctxDB.DBConnector();
                rs = ctxDB.executeQuery(con, build_sql);
    
                while(rs.next()) {
                    his_gross.setId(theId);
                    his_gross.setPid(new StringType(rs.getString("pid")));
                    his_gross.setFileName(new StringType(rs.getString("file_name")));
                }
    
            }catch(SQLException ex) {  
                System.out.println("SQLException :" + ex.getMessage());
            }
    
            if(!his_gross.hasIdElement()) {
                throw new ResourceNotFoundException(theId);
            }
    
            return his_gross;
        }
    }
    반응형

    'Framework > HL7 FHIR' 카테고리의 다른 글

    [HL7/FHIR] HL7가이드 라인 적용 방법 알아보기  (0) 2022.06.08

    댓글

Designed by Tistory.