Search operation
The search operation enables the connector to search for objects on the target system.
The ICF framework handles searches as follows:
-
The application sends a query, with a search filter, to the OpenICF framework.
-
The framework submits the query, with the filter, to the connector.
-
The connector implements the
createFilterTranslator()
method to obtain aFilterTranslator
object. -
The framework then uses this
FilterTranslator
object to transform the filter to a format that theexecuteQuery()
method expects.
You can implement the FilterTranslator
object in two ways:
-
The
FilterTranslator
translates the original filter into one or more native queries.The framework then calls the
executeQuery()
method for each native query. -
The
FilterTranslator
does not modify the original filter.The framework then calls the
executeQuery()
method with the original ICF filter.Using this second approach enables your connector to distinguish between a search and a get operation and to benefit from the visitor design pattern.
Based on the resultsHandlerConfiguration
, the OpenICF framework can perform additional filtering on the returning results. For more information on the resultsHandlerConfiguration
, refer to Configure How Results Are Handled.
The connector facade calls the executeQuery
method once for each native query that the filter translator produces. If the filter translator produces more than one native query, the connector facade merges the results from each query and eliminates any duplicates.
Note that this implies an in-memory data structure that holds a set of UID values. Memory usage, in the event of multiple queries, will be O(N) where N is the number of results. It is therefore important that the filter translator for the connector implement OR
operators, if possible.
Whether the application calls a get
API operation, or a search
API operation, the ICF framework translates that request to a search
request on the connector.
Use the ICF get operation
The GetApiOp
returns null
when the UID does not exist on the resource.
@Test
public void getObjectTest() {
logger.info("Running GetObject Test");
final ConnectorFacade facade = createConnectorFacade(BasicConnector.class, null);
final OperationOptionsBuilder builder = new OperationOptionsBuilder();
builder.setAttributesToGet(Name.NAME);
ConnectorObject co =
facade.getObject(ObjectClass.ACCOUNT, new Uid(
"3f50eca0-f5e9-11e3-a3ac-0800200c9a66"), builder.build());
Assert.assertEquals(co.getName().getNameValue(), "Foo");
}
Use the ICF search operation
@Test
public void searchTest() {
logger.info("Running Search Test");
final ConnectorFacade facade = createConnectorFacade(BasicConnector.class, null);
final OperationOptionsBuilder builder = new OperationOptionsBuilder();
builder.setPageSize(10);
final ResultsHandler handler = new ToListResultsHandler();
SearchResult result =
facade.search(ObjectClass.ACCOUNT, FilterBuilder.equalTo(new Name("Foo")), handler,
builder.build());
Assert.assertEquals(result.getPagedResultsCookie(), "0");
Assert.assertEquals(((ToListResultsHandler) handler).getObjects().size(), 1);
}
Implement the search operation
public FilterTranslator<String> createFilterTranslator(ObjectClass objectClass,
OperationOptions options) {
return new BasicFilterTranslator();
}
public void executeQuery(ObjectClass objectClass, String query, ResultsHandler handler,
OperationOptions options) {
final ConnectorObjectBuilder builder = new ConnectorObjectBuilder();
builder.setUid("3f50eca0-f5e9-11e3-a3ac-0800200c9a66");
builder.setName("Foo");
builder.addAttribute(AttributeBuilder.buildEnabled(true));
for (ConnectorObject connectorObject : CollectionUtil.newSet(builder.build())) {
if (!handler.handle(connectorObject)) {
// Stop iterating because the handler stopped processing
break;
}
}
if (options.getPageSize() != null && 0 < options.getPageSize()) {
logger.info("Paged Search was requested");
((SearchResultsHandler) handler).handleResult(new SearchResult("0", 0));
}
}