Com4j - библиотека, предназначенная для интеграции java-приложений и dll-библиотек, использующих COM-технологию (Component Object Model).
Com4j автоматически импортирует библиотеку типов и генерирует необходимые java-классы.
В качестве примера рассмотрим подключение библиотеки TextAnalyst SDK для анализа содержания текста, смыслового поиска информации и множества других возможностей. Условно-бесплатную версию SDK можно скачать на сайте компании. В каталоге с программой есть 4 необходимые библиотеки: Base.dll, KB.dll, tp.dll и vocobj.dll. Также советую скачать документацию к SDK, в которой есть описание всех COM-интерфейсов и примеры использования на C++ и Visual Basic.
В качестве среды разработки я использую IntelliJ IDEA 12.1.6. Открываем программу и создаем новый проект под названием com4j_example
. Файлы проекта я буду хранить в каталоге C:\projects\other\com4j_example
.
Библиотеку com4j разместим в каталоге C:\projects\other.
Вышеперечисленные dll-файлы SDK скопируем в каталог C:\projects\other\com4j_example\com_lib
.
Также я создал папку lib для хранения jar-файлов проекта (C:\projects\other\com4j_example\lib
) - в эту папку копируем файл com4j.jar и подключаем к проекту, и папку dic - в нее скопируем русский и английский словари SDK (файлы с расширениями .dic, .dat, .xpt, .voc, .suf).
Последний подготовительный этап: регистрация COM-компонентов в системе, для этого используем программу regsvr32.exe (нажимаем Win+R, в открывшемся окне вводим: regsvr32.exe "путь к нужному dll-файлу"). Например, в моем случае это будет так: regsvr32.exe C:\projects\other\com4j_example\com_lib\Base.dll
. Нажимаем Enter и после этого должно появиться сообщение об успешной регистрации. Этот шаг проделываем для всех четырех файлов.
Для этого будем использовать tlbimp.jar, поставляемый вместе с com4j. Запускаем командную строку с правами администратора, переходим в каталог com4j и используем следующую команду:
java -jar tlbimp.jar -o "..." -p "..." полный_путь_к_DLL_файлу
где -o - каталог, в который будем сохранять сгенерированные java-классы, -p - имя пакета.
Выполняем для всех 4 компонентов:
Добавим в пакет один класс Com4j_integrate и один интерфейс Config с основными настройками.
В интерфейсе определим путь к словарям и еще некоторые константы:
package pro.parshinpn;
public interface Config {
// Полный путь к каталогу с словарями
String vocPath = "C:\\projects\\other\\com4j_example\\dic";
// Имя русского словаря
String vocPatternRus = "normal_rus.dic";
// ID документа (множество документов на данном этапе не рассматриваем)
int idDoc = 1;
// Условием окончания перебора узлов является равенство номера ссылки значению END_OF_ENUM
int END_OF_ENUM = -1;
}
Класс Com4j_integrate:
package pro.parshinpn;
import com4j.Com4jObject;
import com4j.Holder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import pro.parshinpn.base.IBase;
import pro.parshinpn.kb.IKnowledgeBase;
import pro.parshinpn.tp.ITextProcessor;
import pro.parshinpn.vocobj.IDictionary;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class Com4j_integrate {
private static IDictionary vocObj;
private static ITextProcessor tpObj;
private static IKnowledgeBase kbObj;
private static IBase baseObj;
// Текст, который введет пользователь
private static String inputText;
/**
* Отвечает за создание и инициализацию объектов для работы с COM-библиотекой.
*/
private static void initLibrary() {
// Создаем объекты COM-компонентов.
vocObj = pro.parshinpn.vocobj.ClassFactory.createDictionary();
tpObj = pro.parshinpn.tp.ClassFactory.createTextProcessor();
kbObj = pro.parshinpn.kb.ClassFactory.createTAKB();
// Полный путь к словарю (рассматриваем только русский язык)
String fullVocPath = Config.vocPath + Config.vocPatternRus;
File voc = new File(fullVocPath);
if (voc.exists()) {
// Загружаем словари
vocObj.vocPath(Config.vocPath);
vocObj.pattern(fullVocPath);
} else {
// Если файл со словарем не найден, то завершаем выполнение программы
assert false;
}
baseObj = processingText(1, 0, 0, 0, 1, 1, 0, 0, 0);
kbObj.dictionary(vocObj);
kbObj.addBase(Config.idDoc, baseObj);
}
/**
* Обрабатывает текст в соответствии с указанными параметрами.
* Результатом обработки является создание объекта класса TA.Base.
* Параметры метода можно посмотреть в документации.
* @return Указатель на объект класса IBase
*/
private static IBase processingText(int metaData,
int onlyUserWrds,
int singleWrds,
int latins,
int buildRef,
int buildSummary,
int phraseThresh,
int linkThresh,
int fullText)
{
tpObj.dictionary(vocObj);
Com4jObject tpObject = tpObj.processText(inputText, metaData, onlyUserWrds, singleWrds, latins, buildRef, buildSummary, phraseThresh, linkThresh, fullText);
return tpObject.queryInterface(IBase.class);
}
/**
* Построение семантической сети в формате XML.
* @return XML-представление семантической сети
*/
private static Document getNetworkInXmlFormat() {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
Document doc = null;
try {
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
doc = docBuilder.newDocument();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
if (doc == null) return null;
/**
* Создаем root-элемент
*/
Element rootElement = doc.createElement("TextAnalystNetwork");
doc.appendChild(rootElement);
int nodeEnumHandle = baseObj.getNodeEnumHandle();
// Узлы текста.
// Используем специальный класс Holder для получения значений по ссылке из библиотеки.
Holder<Integer> id = new Holder<>(),
cnt = new Holder<>(),
wght = new Holder<>(),
attr = new Holder<>();
Holder<String> str = new Holder<>();
// Связи между узлами
Holder<Integer> linkID = new Holder<>(),
wght12 = new Holder<>(),
wght21 = new Holder<>(),
linkCnt = new Holder<>(),
linkAttr = new Holder<>();
for (baseObj.getNextNodeEx(nodeEnumHandle, id, cnt, wght, attr, str);
id.value != Config.END_OF_ENUM;
baseObj.getNextNodeEx(nodeEnumHandle, id, cnt, wght, attr, str)) {
Element nodeElement = doc.createElement("Node");
nodeElement.setAttribute("weight", String.valueOf(wght.value));
nodeElement.setAttribute("name", str.value);
nodeElement.setAttribute("counter", String.valueOf(cnt.value));
nodeElement.setAttribute("attr", String.valueOf(attr.value));
rootElement.appendChild(nodeElement);
/**
* Нумерация и получение связей между узлами
*/
int linkEnumHandle = baseObj.getNodeLinkEnumHandle(id.value);
for (baseObj.getNextNodeLinkEx(linkEnumHandle, linkID, linkCnt, wght12, wght21, linkAttr);
linkID.value != Config.END_OF_ENUM;
baseObj.getNextNodeLinkEx(linkEnumHandle, linkID, linkCnt, wght12, wght21, linkAttr)) {
String linkStr = baseObj.getNodeStr(linkID.value);
Element linkElement = doc.createElement("Link");
linkElement.setAttribute("weight", String.valueOf(wght12.value));
linkElement.setAttribute("name", linkStr);
linkElement.setAttribute("counter", String.valueOf(linkCnt.value));
linkElement.setAttribute("attr", String.valueOf(linkAttr.value));
rootElement.getLastChild().appendChild(linkElement);
}
baseObj.freeNodeLinkEnumHandle(linkEnumHandle);
}
baseObj.freeNodeEnumHandle(nodeEnumHandle);
return doc;
}
public static void main(String[] args) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
System.out.println("Введите текст: ");
inputText = reader.readLine();
initLibrary();
Document doc = getNetworkInXmlFormat();
} catch (IOException e) {
e.printStackTrace();
}
}
}