소프트웨어는 서로 밀접하게 연관된 기능을 구현한 소프트웨어 모듈을 컴포넌트라고 명명한다.
소프트웨어는 컴포넌트를 관리하고 다른 컴포넌트와의 통신을 위해 interface manager를 제공하는데, interface manager는 버스 토폴로지 구조를 이용하며, event와 command 통신 채널을 지원한다.
Figure: Component communication through the interface manager

위에서, main.exe는 component를 포함하는 실행파일로 실제 이름은 구현에 따른다.
interface manager는 main.exe 실행시 component를 로드하고, main.exe 실행시 component를 종료하며, 사용자의 키 입력을 main.exe 또는 component가 event로 발생시킬 수 있도록 적절한 event로 변환한다.
main.exe 또는 component가 interface manager에게 event를 발생시키면, interface manager는 해당 event를 subscribe하는 component의 interface를 통해 event를 전달한다.
main.exe 또는 component는 command를 interface manager를 통해 실행할 수 있는데, 이 경우 interface manager는 해당 command를 실행하는 component의 interface를 통해 command를 호출한다.
interface manager가 component를 관리하고 통신 수단을 제공하기 위해, component는 자신에 대한 설명을 리소스 파일을 통해 다음과 같이 기술한다:
<Component> <General> … </General> <Keys_To_Events> … </Keys_To_Events> <Events> … </Events> <Commands> … </Commands> </Component> |
General은 component 이름, 디버거 빌드 이름, 릴리즈 빌드 이름을 표시한다. 예를 들면 다음과 같다:
<General> <Name>Scanner</Name> <Debug>Scannerd.dll</Debug> <Release>Scanner.dll</Release> </General> |
Keys_To_Events는 component가 key를 event로 변환하기 위한 정보를 포함한다. 예를 들면 다음과 같다:
<Keys_To_Events> <General> <Priority type=”int”>0</Priority> <No_Iterative type=”bool”>true</No_Iterative> <Exclusive type=”bool”>true</Exclusive> </General> <List> <Key_To_Event> <Key>VCP_Key</Key> <Event>VCP_Event</Event> </Key_To_Event> </List> </Keys_To_Events> |
interface manager는 스택 구조를 이용하여 사용자가 입력한 key를 event로 변환한다. 예를 들면 아래 그림에서, 스택에 컴포넌트 a, b, c 세 개가 존재할 때, 사용자가 키를 누르면, interface manager는 컴포넌트 c의 Key_To_Events.List에 해당 key가 있는지를 살펴본다. 만약 key가 존재한다면 key에 대응하는 event를 리턴한다.
만약 컴포넌트 c에 해당 key가 없다면, c의 No_Iterative 속성이 false이므로 컴포넌트 b의 Key_To_Events.List에 해당 key가 있는 살펴본다. 만약 key가 존재한다면 key에 대응하는 event를 리턴한다. 만약 key가 없다면 컴포넌트 b의 No_Iterative 속성이 true이므로 interface manager는 invalid event를 리턴한다.
Key_To_Event에서 명시하는 event 이름은 글로벌 이름이다.
Figure: Component stack operation

key를 event로 변환하기 위해서는 컴포넌트를 스택의 top으로 푸쉬해야 하며, 이를 위해 interface manager의 activate_component()를 호출한다. key를 event로 변환할 필요가 없을 경우에는 컴포넌트를 스택에서 팝해야 하며, 이를 위해 interface manager의 deactivate_component()를 호출한다.
컴포넌트를 스택의 top으로 푸쉬할 경우, interface manager는 해당 컴포넌트의 priority보다 큰 수를 가진 컴포넌트를 스택에서 팝 시킨 후에 해당 컴포넌트를 스택의 탑으로 푸시한다. 스택에 priority가 같은 컴포넌트가 존재할 경우 Exclusive 속성이 true이 컴포넌트를 팝시키며, false인 경우 컴포넌트를 유지시킨다.
컴포넌트를 스택에 푸쉬하거나 팝할 경우, 다음과 같은 컴포넌트 함수를 호출하여 컴포넌트가 스택의 top인지 아닌지 그리고 스택에 들어왔는지 혹은 빠져 나갔는지를 알려준다:
- kill_focus() – 컴포넌트가 스택의 top이 아님
- deactivated() – 컴포넌트가 스택에서 빠져나감
- activated() – 컴포넌트가 스택에 들어옴
- set_focus()- 컴포넌트가 스택의 top임.
Events는 컴포넌트가 발생하는 event와 subscribe하는 event의 목록을 다음과 같이 표시한다. 예를 들면, 다음과 같다:
<Events> <Event> <Local> local_firing_name</Local> <Global>global_firing_name</Global> <Outgoing type=”bool”>true</Outgoing> </Event> <Event> <Local>local_name</Local> <Global>global_name</Global> <Incoming type=”bool”>true</Incoming> <Outgoing type=”bool”>true</Outgoing> </Event> <Event> <Local>local_subscribing_name</Local> <Global>global_subscribing_name</Global> </Event> </Events> |
Event는 컴포넌트에서 사용하는 로컬이름과 전체 컴포넌트에서 사용하는 글로벌이름이 존재한다. Event는 다음과 같이 Incoming과 Outgoing 파라메터를 사용하여 컴포넌트가 발생하는 이벤트인지 혹은 subscribe하는 이벤트인지를 명시한다:
Table: Incoming and Outgoing for Event
No. | Incoming / Outgoing | 내용 |
---|---|---|
1 | Incoming / Outgoing 표시 안함 | subscribe하는 이벤트 |
2 | Incoming만 true로 표시 | |
3 | Outgoing만 true로 표시 | 발생시키는 이벤트 |
4 | Incoming / Outgoing 모두 true로 표시 | 발생과 subscribe를 동시에 하는 이벤트 |
위에서, 컴포넌트가 local_firing_event를 interface manager에게 발생시키면 interface manager는 local_firing_event를 global_firing_event로 바꿔 해당 글로벌 이벤트를 subscribe하는 복수의 컴포넌트에게 전달하는데 이때 글로벌 이벤트는 subscribe하는 개별 컴포넌트에서 명시된 로컬 이벤트로 변환되어 전달된다.
Commands는 컴포넌트가 실행하는 또는 호출하는 명령의 목록을 명시한다. 예를 들면 다음과 같다:
<Commands> <Command> <Local> local_cmd_name</Local> <Global>global_cmd_name</Global> <Outgoing type=”bool”>true</Outgoing> </Command> <Command> <Local>local_cmd2_name</Local> <Global>global_cmd2_name</Global> <Incoming type=”bool”>true</Incoming > </Command> <Command> <Local>local_cmd3_name</Local> <Global>global_cmd3_name</Global> </Command> </Commands> |
Command는 컴포넌트에서 사용하는 로컬이름과 전체 컴포넌트에서 사용하는 글로벌이름이 존재한다. Command는 다음과 같이 Incoming과 Outgoing 파라메터를 사용하여 컴포넌트가 실행하는 명령인지 또는 호출하는 명령인지를 명시한다:
Table: Incoming and Outgoing for Command
No. | Incoming / Outgoing | 내용 |
---|---|---|
1 | Incoming / Outgoing 표시 안함 | 컴포넌트가 실행하는 명령 |
2 | Incoming만 true로 표시 | |
3 | Outgoing만 true로 표시 | 컴포넌트가 호출하는 명령 |
4 | Incoming / Outgoing 모두 true로 표시 | 지원안함. |
명령은 하나의 컴포넌트에 의해 실행된다.
command manager의 리소스는 추가적으로 로드할 컴포너트 목록을 Components 파라메터에 다음과 같이 명시한다:
<Components> <Component no_esc_char=”true”>Scanner\Scanner.xml</Component> <Component no_esc_char=”true”>Control_Panel\Control_Panel.xml</Component> <Component no_esc_char=”true”>Patient\Patient.xml</Component> <Component no_esc_char=”true”>Setup\Setup.xml</Component> <Component no_esc_char=”true”>System_Power_Controls\System_Power_Controls.xml </Component> </Components> |
interface manager가 로드되면, interface manager는 Components 파라메터의 하위 파라메터를 순회하며 Component 리소스를 파싱하여 해당 컴포넌트를 로드한다.