Статьи

Поиски в NetBeans объяснены!

Поиск является одной из наиболее важных частей платформы NetBeans . Они используются почти везде, и в большинстве случаев, когда вы спрашиваете что-то в списке рассылки, вы получаете ответ «Используйте поиск!». Много раз, когда использование Lookups объясняется, оно находится в очень специфическом контексте, например, управление выбором или ServiceLoaders. Это делает Lookups сложными и трудными для понимания, хотя на самом деле они очень простые и чрезвычайно мощные.

Вот почему я думаю, что пришло время написать статью, которая объясняет, что на самом деле поиски и как они работают. В последующих частях я объясню, как их можно использовать для решения некоторых общих проблем.

Поиск как структура данных

Итак, сначала давайте посмотрим на Lookup как структуру данных. Lookup — это карта с объектами класса в качестве ключей и набором экземпляров ключевого объекта класса в качестве значений. Дополнительной функцией Lookup является то, что вы можете прослушивать изменения того, что там находится. Это так просто! Если вы хотите запросить поиск его содержимого, вы можете сделать это следующим образом:

Lookup  lookup = //get a lookup somewhere...
Collection <String> strings =lookup.lookupAll(String.class);

Если вы хотите прослушать изменения, вы добавляете свой Listener в Lookup.Result внутренний класс, который представляет результат запроса. Таким образом, вы добавляете Listener, который прослушивает добавление или удаление объектов определенного класса:

Lookup.Result <String> strings = lookup.lookupResult(String.class);
strings.allItems();
strings.addLookupListener(new LookupListener(){
@override
public void resultChanged(LookupEvent e){
// do something
}}
);

Вот как вы обычно используете существующий поиск. Если вы хотите создать его, есть несколько реализаций, которые могут вам помочь. Самый простой из них — Lookups.Singleton, Lookup, который содержит только один объект:

Lookup simple = Lookups.singleton("Hello World!"); 

Также есть реализация для создания поиска с более чем одной записью, по-прежнему с фиксированным содержимым:

Lookups moreElements = Lookups.fixed( "Hello", "World", new Integer(5) ); 

Если вы хотите использовать Lookup для динамического добавления материала, вам нужно выбрать реализацию, которая поддерживает это. Наиболее гибким является использование объекта InstanceContent для добавления и удаления содержимого:

InstanceContent content = new InstanceContent();
Lookup dynamicLookup = new AbstractLookup(content);
content.add("Hello");
content.add(5);

Слушатели, зарегистрированные для соответствующего класса, будут уведомлены, когда что-то изменится. Если вы хотите запрашивать более одного Lookup одновременно, вы можете использовать ProxyLookup. Это, например, объединяет два поиска, созданных выше, в один:

ProxyLookup proxy = new ProxyLookup(dynamicLookup, moreElements); 

Lookup.Provider

Если ваш объект имеет Lookup для хранения множества вещей, вы можете сделать его доступным для других, реализовав Lookup.Provider интерфейс только с одним методом:

public Lookup getLookup();

Опять же, чрезвычайно просто. Кто-то, кто интересуется тем, что находится в вашем поиске объектов, может попросить об этом и зарегистрировать слушателя. В NetBeans TopComponents реализуют этот интерфейс, поэтому вы можете запросить любой TopComponent для его поиска. Самый простой способ получить доступ к большинству TopComponents через их ID:

TopComponent tc = WindowManager.getDefault().findTopComponent("AnInterestingTopComponent");
Lookup tcLookup = tc.getlookup();

Поскольку большинство TopComponents помещают в свой Lookup все, что выбрано, например записи в списке, вы можете добавить прослушиватель для отслеживания выбора в TopComponent. Если вас, например, интересуют выбранные узлы, вы можете сделать это следующим образом:

Lookup.result <Node> noderesult = tcLookup.lookupResult(Node.class);
result.allInstances();
noderesult.addLookuplistener(myLookupListener);

Это особенно удобно, когда вы хотите предоставить Master-Detail-View. Если вы хотите предоставить свой собственный Lookup в вашем TopComponent, вы делаете это так:

associateLookup(mylookup); 

Глобальный отбор

Иногда вас может интересовать не только то, что выбрано в одном конкретном TopComponent, но и то, на что TopComponent в настоящее время имеет фокус. Это также легко, потому что NetBeans предоставляет Lookup, который проксирует Lookup TopComponent, который в настоящее время имеет фокус. Чтобы использовать это, вам просто нужно сделать это:

Lookup global = Utilities.actionsGlobalContext();

Вы можете использовать это как любой другой Lookup и зарегистрировать своих слушателей, без магии.

Вершины

Узлы также реализуют Lookup.Provider, поэтому вы также можете запросить у них их Lookup. Что-то полезное для хранения внутри Lookup узла — это DataObject, который он может представлять. Если вы используете узлы, вы, вероятно, делаете это в сочетании с Explorer API для их отображения. Если вы сделаете это, вы обычно создадите поиск для вашего TopComponent с помощью ExplorerManager:

associateLookup(ExplorerUtils.createLookup ( explorermanager, this.getActionMap() ) );

Результирующий поиск также передает содержимое выбранного поиска узлов. Таким образом, все, что кого-то может заинтересовать, отображается в вашем поиске TopComponent.

Service Loader и другое использование

Как вы видели, Lookups на самом деле очень простая, но мощная концепция. Некоторые статьи здесь о зоне NetBeans также охватывают использование поисков для загрузки служб в приложении RCP NetBeans, что также является важным использованием. Для этого NetBeans обеспечивает поиск по умолчанию, который ищет определенные службы для регистрации служб, например, в папке META-INF / services файла jar модулей и в файле layer.xml модулей. Если вы заинтересованы в получении экземпляра реализации Сервиса, вы можете сделать это следующим образом:

Collection <ServiceInterface> services= Lookup.getDefault.lookupAll(ServiceInterface.class); 

Если вы зарегистрируете свой сервис в layer.xml, вы можете получить поиск для определенной папки следующим образом:

Lookup lkp = Lookups.forPath("ServiceProviders");

Я думаю, это все, что вам нужно знать, чтобы начать работу с Lookups, так что повеселитесь, это действительно просто.