|
|
|
|
| |||||||||||||||||||
Acronym Expander 플러그인을 개발하는 첫 번째 단계는 Lotus Sametime 플러그인을 하우징 하는 Eclipse 플러그인 프로젝트를 생성하는 것이다. 시작하려면, File - New - Project 순으로 선택하여 New Project 마법사를 시작한다. New Project 마법사에서, Plug-in Project를 선택하고 Next를 클릭한다.
다음에는, Project Name 필드에서, 프로젝트의 이름을 입력한다: com.devworks.example.acronym.
그런 다음, 플러그인 프로퍼티를 편집할 수 있는 스크린이 나타난다. "This plug-in will make contributions to the UI" 옵션이 선택되었는지를 확인하고 Finish를 클릭한다.
Finish를 클릭한 후에, Plug-in Development Perspective(그림 3)로 전환할 것인지를 묻는다. Yes를 클릭하면 Plug-in Development Perspective로 전환한다.
|
|
|
Lotus Sametime V7.5.1 플러그인을 개발하려면, 대상 플랫폼을 Eclipse에서 Lotus Sametime으로 바꿔야 한다. Target Platform에 대한 Eclipse 프레퍼런스를 바꾼다. Window - Preferences 순으로 바꾼다. Preferences 다이얼로그 박스가 나타난다. (그림 4) 왼쪽 페인에서, Plug-in Development - Target Platform을 선택한다. Lotus Sametime Connect의 설치 디렉토리를 Target Platform의 위치로 지정한다. 이 경우, C:\Program Files\IBM\Sametime Connect이다. OK를 클릭한다.
Target platform이 지정되었으므로, Lotus Sametime Connect를 확장할 준비가 되었다.
|
|
|
이제 Acronym Expander 플러그인을 구현할 차례이다. Acronym과 관련 확장 의미를 정의할 방법이 필요하다.
Acronym 디렉토리에서 여러분이 원하는 Acronym들을 입력하려면(Acronym Expander 플러그인이 Acronym을 확장하기 위해 사용하는 것), Eclipse Preferences 페이지를 사용한다. Acronym Expander Preferences 페이지는 그림 5에 나타나 있다.
Acronym Expander Preferences 페이지에 New 버튼을 클릭한 후에, 메시지 박스(그림 6)이 나타나면 새로운 Acronym과 확장 폼을 입력할 수 있다. 보다시피, 입력 포맷은 ACRONYM = Expanded 폼이다.
|
|
|
com.devworks.example.acronym.preferences.PreferenceConstants라고 하는 클래스를 만들어서 Preferences 페이지가 사용하는 스트링 필드 이름을 외부화 했다. File - New Class 순으로 선택함으로써, 이 클래스를 생성한다. New Java Class 다이얼로그 박스가 그림 7처럼 나타난다. 패키지 이름(com.devworks.example.acronym.preferences)과 Java 클래스 이름(PreferenceConstants)을 채운다.
com.devworks.example.acronym.preferences.PreferenceConstants 클래스는 패키지 익스플로러에 나타난다. 자동 생성된 코드를 아래 보이는 코드로 바꾼다.
public class PreferenceConstants {
public static String ACRONYM_LIST = "AcronymList";
}
이 코드 스니펫에서, 상수 ACRONYM_LIST는 프레퍼런스 스토어에 있는 데이터를 가져다가 설정하는데 사용되는 키(key)이다. 이 키는 com.devworks.example.acronym.preferences.AcronymPreferencePage 클래스와 com.example.acronym.preferences.AcronymListStore 클래스에 의해 사용된다.
|
|
|
Plug-in Manifest Editor를 사용하여 새로운 확장 정의하기
Acronym Expander 전용의 Eclipse Preferences 페이지를 추가하려면, Eclipse 확장 포인트를 사용한다. Plug-in Manifest Editor를 사용하여 확장 포인트를 정의한다. Plug-in Manifest Editor를 열려면 META-INF/MANIFEST.MF 파일을 열고 Extensions 탭을 클릭한다. Extensions 창은 그림 8에 나타나 있다.
Extensions 탭에서 Add 버튼을 클릭한다. New Extension 마법사가 그림 9처럼 나타난다. "Show only extension points from the required plug-ins." 옵션의 선택을 해제한다. Extension Point 필터에서 org.eclipse.ui.preferencePages를 입력한다. 아래 페인에서 org.eclipse.ui.preferencePages를 선택하고 Finish를 클릭한다.
플러그인 org.eclipse.ui를 그림 10에 보이는 플러그인 종속 리스트에 추가할 것인지를 묻는다. Yes를 클릭하고 org.eclipse.ui를 플러그인 종속 리스트에 추가한다. org.eclipse.ui를 종속 리스트에 추가할 것인지를 묻지 않는다면, 이미 플러그인 종속 리스트의 일부인 것이다.
Plug-in Manifest Editor를 저장하고 닫는다.
|
|
|
(New Extension 마법사에서 만든) org.eclipse.ui.preferencePages의 확장을 커스터마이징 해보자. plugin.xml 파일을 편집한다. plugin.xml 파일에는 org.eclipse.ui.preferencePages 확장 포인트에 대한 확장이 포함되어 있다.
<extension
point="org.eclipse.ui.preferencePages">
</extension>
이 Extension의 편집 결과를 listing 1에서 볼 수 있다.
<extension
point="org.eclipse.ui.preferencePages">
<page class="com.devworks.example.acronym.preferences.AcronymPreferencePage"
id="com.devworks.example.acronym.preferences.AcronymPreferencePage"
name="Acronym Expander"/>
</extension>
|
Listing 1에서 보듯, org.eclipse.ui.preferencePages 확장 포인트의 사용을 지정한다. 이 확장 포인트는 플러그인이 Eclipse Preferences 페이지가 Preferences 창에 기여하도록 하는 방식을 제공한다. 확장 포인트 정의에서, 이 페이지(com.devworks.example.acronym.preferences.AcronymPreferencePage)와 사용자에게 나타나는 이름(우리는 Preferences 페이지에 Acronym Expander를 디스플레이 하기로 결정했다.)을 나타내는데 사용되는 고유 아이디를 지정한다. 또한 org.eclipse.ui.IWorkbenchPreferencePage 인터페이스를 구현하는 클래스로서 com.devworks.example.acronym.preferences.AcronymPreferencePage를 지정한다. 이 인터페이스는 org.eclipse.ui.preferencePages 확장 포인트를 확장할 때 구현해야 하는 것이다. 그림 11에 나타난 클래스 계층을 보자.
com.devworks.example.acronym.preferences.AcronymPreferencePage 클래스는 Listing 2에 나타나 있다. 여러분도 보듯, createFieldEditors 메소드에서, 고유의 리스트 에디터 com.devworks.example.acronym.preferences.AcronymListEditor를 만든다.
public class AcronymPreferencePage
extends FieldEditorPreferencePage
implements IWorkbenchPreferencePage {
public AcronymPreferencePage() {
super(GRID);
setPreferenceStore(Activator.getDefault().getPreferenceStore());
}
public void createFieldEditors() {
AcronymListEditor editor = new AcronymListEditor(PreferenceConstants.ACRONYM_LIST,
"Acronyms", getFieldEditorParent());
addField(editor);
}
public void init(IWorkbench workbench) {}
}
|
|
|
|
com.devworks.example.acronym.preferences.AcronymListEditor 클래스는 Eclipse 클래스 org.eclipse.jface.preference.ListEditor를 확장한다. ListEditor는 org.eclipse.jface.preference.FieldEditor 클래스를 확장한다. FieldEditor는 Preferences 페이지에서 사용자에 의해 수정될 수 있는 값을 나타내는 추상 클래스이다. 그림 12는 AcronymListEditor 클래스의 UML 클래스 다이어그램으로서, Eclipse 부모 클래스에 대한 관계와 인풋의 유효성 검사를 할 수 있는 밸리데이터 클래스를 나타내고 있다.
ListEditor는 데이터 리스트를 나타내는 추상 클래스이다. AcronymListEditor 클래스는 ListEditor의 확장이다. AcronymListEditor 필드를 가리키는 화살표를 주목하라. (그림 13)
Listing 3은 AcronymListEditor의 클래스 정의이다. 이 코드에서 내부 클래스 MyInputValidator는 Acronym 리스트에 대한 인풋의 유효성 검사를 담당하고 있다. 단순하게 하기 위해, 우리는 밸리데이터가 실행될 때마다 NULL 값을 리턴함으로써 리스트에 대한 엔트리의 유효성 검사를 하지 않기로 했다.
public class AcronymListEditor extends ListEditor {
public class MyInputValidator implements IInputValidator {
public String isValid(String arg0) {
return null;
}
}
protected void adjustForNumColumns(int arg0) {
// TODO Auto-generated method stub
super.adjustForNumColumns(arg0);
}
public AcronymListEditor(String arg0, String arg1, Composite arg2) {
super(arg0, arg1, arg2);
adjustForNumColumns(2);
}
protected String createList(String[] arg0) {
String encodedArray = "";
if (arg0 != null) {
int size = arg0.length;
for (int i=0; i<size; i++)
encodedArray = encodedArray.concat(arg0[i] + ";");
}
System.out.println(encodedArray);
return encodedArray;
}
|
Listing 4의 코드는 Sametime 사용자에게서 인풋을 모은다.
protected String getNewInputObject() {
InputDialog dialog = new InputDialog(new Shell(),"Enter an Acronym",
"Enter an Acronym followed by
the series of words which represent that acronym. \n \n \t Example: IBM = International
Business Machines","", new MyInputValidator());
dialog.create();
dialog.open();
String text = dialog.getValue();
return text;
}
|
Acronym 데이터는 스트링으로서 저장된다. Listing 5의 코드는 Acronym 데이터를 스트링에서 스트링 어레이로 변환한다. 특정 단어가 Acronym인지 여부를 향후 검사하기 위함이다.
protected String[] parseString(String arg0) {
StringTokenizer stok = new StringTokenizer(arg0, ";");
int arraySize = stok.countTokens();
String[] decodedArray = new String[arraySize];
for (int i=0; i<arraySize; i++) {
decodedArray[i] = stok.nextToken(";");
}
return decodedArray;
}
}
|
|
|
|
Preferences 페이지를 만든 후에, 이를 초기화 할 방법이 필요하다. org.eclipse.core.runtime.preferences 확장 포인트를 사용한다. 이 확장 포인트를 사용하여 com.devworks.example.acronym.preferences.PreferenceInitializer 클래스가 Listing 6의 확장 포인트 선언에 나타난 것처럼 프레퍼런스를 초기화 하도록 지정한다.
<extension
point="org.eclipse.core.runtime.preferences">
<initializer class="com.devworks.example.acronym.preferences.PreferenceInitializer"/>
</extension>
|
선행하는 확장 정의를 plugin.xml 파일에 복사하여 붙인다. org.eclipse.core.runtime.preferences 확장 포인트는 org.eclipse.ui 플러그인에 의존하므로, Plug-in Manifest Editor를 사용하여 플러그인 종속 리스트를 편집 할 필요가 없다. 이미 org.eclipse.ui 플러그인을 플러그인 종속 리스트에 추가했다.
com.devworks.example.acronym.preferences.PreferenceInitializer 클래스는 Preferences 페이지가 처음 열릴 때 호출된다.
public class PreferenceInitializer extends AbstractPreferenceInitializer {
public void initializeDefaultPreferences() {
IPreferenceStore store = Activator.getDefault()
.getPreferenceStore();
store.setDefault(PreferenceConstants.ACRONYM_LIST,
"");
}
}
|
PreferenceInitializer 클래스는 Preferences 페이지를 기본 값으로 로딩하는데 사용된다. 이 경우, 어떤 디폴트 값도 설정하지 않기로 결정했다. 기본 값은 프레퍼런스를 위해 설정된 값이 없을 경우에만 사용된다. 예를 들어, 우리의 모든 Lotus Sametime 사용자들을 위해 사전 로딩된 Acronym 사전이 필요하다고 생각해 보자. PreferenceInitalizer 클래스의 setDefault 메소드에 있는 사전 로딩된 사전에 대한 값을 설정할 수 있다. 결과적으로, 사용자가 사전을 수정하자마자, 이 사전은 PreferenceInitializer에 정의된 기본 값을 대신하여 사용된다. 다시 말해서, 특정 필드용 기본 값들은 그 필드용 사용자 값이 무효일 때 사용된다. 우리의 경우, 어떤 기본 값도 로딩하지 않기로 결정했다. Lotus Sametime Connect 사용자가 고유의 Acronym 리스트를 로딩하도록 했다.
|
|
|
Acronym Expander 액션으로 Acronym Expander 실행하기
AcronymExpander 플러그인은 Lotus Sametime Connect 사용자의 의향에 따라 켜거나 꺼질 수 있다. 그림 14에서 보듯, Acronym Expander 버튼은 Lotus Sametime 툴바에 추가되었다.
Acronym Expander 기능을 토글링 할 수 있도록, com.ibm.collaboration.realtime.chatwindow.chatAction 확장 포인트를 사용했다. (Listing 8)
<extension point="com.ibm.collaboration.realtime.chatwindow.chatAction"> <chatAction class="com.devworks.example.acronym.AcronymChatWindowAction" displayName="Acronym Expander" id="com.devworks.example.acronym.AcronymChatWindowAction" image="icon/enabled.gif" path="buddy/end" showsFor="both" tooltipText="Acronym Expander" type="buddy"/> </extension> |
com.ibm.collaboration.realtime.chatwindow.chatAction 확장을 정의하려면, "Plug-in Manifest Editor를 사용하여 새로운 확장 정의하기" 섹션에서 따라갔던 간계를 반복한다. 단, 확장 포인트로서 com.ibm.collaboration.realtime.chatwindow.chatAction을 지정하는 것만 제외한다. 마법사가 com.ibm.collaboration.realtime.chatwindow 플러그인을 플러그인 종속 리스트에 추가하도록 하라.
확장 포인트 정의에서, enabled.gif 이미지에 대한 레퍼런스를 보게 된다. 이미지를 클릭하면 Acronym Expander 기능을 실행할 수 있다. 이 이미지에 대한 클래스 핸들링 클릭은 com.devworks.example.acronym.AcronymChatWindowAction이다. 또한, Listing 9에 나타난 com.devworks.example.acronym.AcronymChatWindow 액션 클래스에 대한 레퍼런스는 확장 포인트 정의에 있다.
public class AcronymChatWindowAction extends ChatWindowAction {
public void run() {
//Change the status of isEnbaled, and get the value after the status change.
boolean isEnabled = AcronymExpanderHandler.toggleEnabled();
if (isEnabled)
MessageDialog.openInformation(null, "Acronym Expander Status",
"Acronym Expansion is now Enabled");
else
MessageDialog.openInformation(null, "Acronym Expander Status",
"Acronym Expansion is now Disabled");
}
}
|
사용자가 Acronym Expander 버튼을 클릭하면, 선행 클래스의 run 메소드가 호출된다. 버튼이 클릭되면, AcronymExpanderHandler 클래스의 toggleEnabled 메소드를 호출함으로써 Acronym Expander의 상태를 토글링 한다. Acronym Expander 플러그인의 현재 상태로 메시지 박스를 디스플레이 한다.
|
|
|
MessageHandlerListener 확장 포인트를 사용하여 메시지 가져오기
com.ibm.collaboration.realtime.messages.MessageHandlerListener 확장 포인트는 사용자가 Lotus Sametime 사용자에게 메시지를 보내기 전에 사용자가 Lotus Sametime 메시지를 리스닝 하고 중재하는 리스너를 만들 수 있도록 한다. 사용자에게 가기 전에 메시지를 가로채려면, 확장 포인트 클래스가 com.ibm.collaboration.realtime.messages.MessageHandlerPreCallback 클래스를 확장하도록 지정되어야 한다.
확장 포인트 정의(Listing 10)은 com.ibm.devworks.example.acronym.AcronymExpanderCallback이라고 하는 클래스의 사용을 지정한다.
<extension point="com.ibm.collaboration.realtime.messages.MessageHandlerListener"> <messageHandlerCallback class="com.devworks.example.acronym.AcronymExpanderCallback" id="com.ibm.collaboration.realtime.sample.acronymexpander.messageHandlerCallback"/> </extension> |
"Plug-in Manifest Editor를 사용하여 새로운 확장 정의하기" 섹션에서 설명한 대로 선행하는 확장을 plugin.xml 파일에 추가한다. 마법사가 com.ibm.collaboration.realtime.messages 플러그인을 플러그인 종속 리스트에 추가하도록 하라.
여러분이 나중에 필요로 할 클래스인, com.ibm.collaboration.realtime.messages.MessageHandlerPreCallback 클래스는 com.ibm.collaboration.realtime.magiccarpet 플러그인을 필요로 한다. 이 부분에서, com.ibm.collaboration.realtime.magiccarpet 플러그인을 플러그인 종속의 리스트에 추가해야 한다. 이렇게 하려면, META-INF/MANIFEST.MF를 열어서 Plug-in Manifest Editor를 연다. Dependencies 탭을 선택하고 Add 버튼을 클릭한다. (그림 15)
Plug-in Selection 다이얼로그 박스가 나타나면, 텍스트 박스에 com.ibm.collaboration.realtime.maggiccarpet을 입력하여 다른 플러그인을 가려낸다. com.ibm.collaboration.realtime.maggiccarpet 플러그인을 선택하고 OK를 클릭한다.
Plug-in Manifest Editor를 저장하고 닫는다.
|
|
|
AcronymExpanderCallback 클래스는 Listing 11에 나타나 있다. 이 클래스의 생성자가 매개변수로서 com.ibm.collaboration.realtime.messages.MessageHandler 객체를 어떻게 취하는지를 주목하라. AcronymExpanderCallback 클래스는 MessageHandlerListener 확장 포인트에 의해 참조되는 클래스이다. AcronymExpanderCallback 클래스는 AcronymExpanderHandler를 사용한다. (그림 16)
Listing 11. AcronymExpanderCallback 클래스
public class AcronymExpanderCallback extends MessageHandlerPreCallback {
public AcronymExpanderCallback() {
super(new AcronymExpanderHandler());
}
}
|
AcronymExpanderCallback 클래스로 보내진 메시지를 캡쳐하려면, com.ibm.collaboration.realtime.messages.MessageHandler 클래스의 하위 클래스를 제공한다.
이 클래스의 확장은 com.devworks.example.acronym.AcronymExpanderHandler 클래스이고, 이는 Listing 12에 나타나 있다.
public class AcronymExpanderHandler extends DefaultMessageHandler {
private static boolean isEnabled = true;
public static boolean toggleEnabled() {
isEnabled = !isEnabled;
return isEnabled;
}
|
Acronym Expander 버튼이 클릭되어 Acronym Expander 플러그인 기능을 실행 또는 실행 중지하면, AcronymExpandHandler 클래스의 toggleEnabled 메소드가 호출된다.
또한 AcronymExpanderHandler 클래스에서, 부모 클래스의 handleMessage 메소드를 오버라이드 하는데, 이는 매개변수로서 ImTextReceivedMessage와 ManyToManyTextReceivedMessage 객체를 취한다. (Listing 13) 이 오버라이딩 메소드에서, expandAcronyms(ImMessage) 메소드를 호출한다.
public void handleMessage(ImTextReceivedMessage message)
{
expandAcronyms(message);
}
public void handleMessage(ManyToManyTextReceivedMessage message)
{
expandAcronyms(message);
}
public void handleDefaultMessage(Message arg0) {
}
|
|
|
|
앞서 언급했듯이, Acronym 확장은 사용자가 이것이 발생하는 것을 보기 전에 발생한다. 이전 섹션의 handleMessage 메소드에 의해 호출된 expandAcronyms 메소드는 com.devworks.example.acronym.AcronymListStore 클래스에 의존하여 Acronym을 확장한다. AcronymExpanderHandler 클래스의 expandAcronyms 메소드에서, 먼저 Acronym 확장이 실행되는지를 확인한다. (isEnabled Boolean 변수의 값에 의해 결정된다.) 다음에, Acronym 확장이 실행되면, 이 Acronym을 AcronymListStore 클래스의 메소드로 확장한다: expandMessage (다음 섹션의 "AcronymListStore" 참조). 그리고 나서 메시지를 확장된 Acronym 텍스트로 설정한다. (Listing 14)
public void expandAcronyms(ImMessage message) {
if (isEnabled) {
String text = message.getText();
if (text != null) {
String acronym = AcronymListStore.expandMessage(text);
message.setText(acronym);
}
}
}
}
|
|
|
|
AcronymListStore 클래스는 두 개의 정적 메소드, expandMessage와 getAcronymMap을 갖고 있다. Listing 15의 getAcronymMap 메소드는 프레퍼런스 스토어에서 Acronym 리스트의 HashMap 표현을 가져온다.
public static HashMap getAcronymMap() {
String acronymListString = Activator.getDefault().getPreferenceStore()
.getString(PreferenceConstants.ACRONYM_LIST);
HashMap acronymMap = new HashMap();
StringTokenizer stok = new StringTokenizer(acronymListString, ";");
int arraySize = stok.countTokens();
for (int i=0; i<arraySize; i++) {
String temp = stok.nextToken(";");
if (temp.indexOf('=') != -1) {
StringTokenizer keyValue = new StringTokenizer(temp, "=");
acronymMap.put(keyValue.nextToken().trim(), keyValue.nextToken());
}
}
return acronymMap;
}
|
이 디자인에서, Acronym 정보를 저장하고 있는 HashMap을 캐싱하는 것을 고려해 볼 수 있지만, Acronym 사전의 동적인 업데이트를 지원하기로 했기 때문에 캐싱하지 않기로 한다.
Acronym을 확장하는 작업은 Listing 16의 expandMessage 메소드에 의해 핸들된다. 이 메소드는 메시지 스트링의 확인된 단어를 통해 반복하고 acronymMap 객체에 분석 할 단어가 포함되어 있는지를 검사한다. 만약 있다면, 이 Acronym에 대한 관련 확장 텍스트가 검색되고 사용자에 맞게 메시지 스트링이 나누어진다. 메시지의 모든 단어가 분석된 후에(필요할 경우 대체도 가능함), 컨트롤은 사용자에게 나타날 수 있도록 인스턴트 메시징 클라이언트로 리턴한다.
public static String expandMessage(String unexpandedMessage) {
HashMap acronymMap = getAcronymMap();
StringTokenizer stok = new StringTokenizer(unexpandedMessage, " <>!.?,:", true);
String expandedString = "";
int bracketCount = 0;
while (stok.hasMoreTokens()) {
String preString = stok.nextToken();
if (preString.equals("<"))
bracketCount++;
if ((acronymMap.containsKey(preString))&&(bracketCount==0))
expandedString = expandedString.concat((String)acronymMap.get(preString));
else
expandedString = expandedString.concat(preString);
if (preString.equals(">"))
bracketCount--;
}
System.out.println(expandedString);
return expandedString.trim();
}
|
|
|
|
Eclipse에서 Lotus Sametime V7.5.1 플러그인을 갖춘 Lotus Sametime V7.5.1을 실행하려면, Run 메뉴로 가서 Run을 선택한다. Run 마법사가 나타난다. Run 마법사를 사용하여 새로운 설정을 만든다. Eclipse Application을 오른쪽 클릭하고 New를 클릭한다. (그림 17)
기본 사항들을 수락하고 Run을 클릭하여 설정을 실행한다.
|
|
|
IBM Lotus Sametime Connect에서 인스턴트 메시지가 사용자에게 나타나기 전에 이를 가로채는 방법을 배웠다. 인터셉트는 com.ibm.collaboration.realtime.messages.MessageHandlerListener 확장 포인트를 사용하여 수행되었다. 이 확장 포인트를 사용하여 Lotus Sametime 플러그인을 구현하여 Acronym의 확장된 형태를 보여주었다. 이는 단지 Acronym 확장에만 국한되지 않는다