OIM 11.1.1.5 Develop Connectors using ICF and SPI APIS.. Part 2 Create connector class for the Flat File Connector by implementing the org.identityconnectors.framework.spi.Connector interface.
This class implements the CreateOp, DeleteOp, SearchOp and UpdateOp interfaces and thus supports all four operations. The FlatFileMetadata, FlatFileParser and FlatFileWriter classes are supporting classes.
package org.identityconnectors.flatfile;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.identityconnectors.flatfile.io.FlatFileIOFactory;
import org.identityconnectors.flatfile.io.FlatFileMetadata;
import org.identityconnectors.flatfile.io.FlatFileParser;
import org.identityconnectors.flatfile.io.FlatFileWriter;
import org.identityconnectors.framework.api.operations.GetApiOp;
import org.identityconnectors.framework.common.exceptions.AlreadyExistsException;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeInfo;
import org.identityconnectors.framework.common.objects.AttributeInfoBuilder;
import org.identityconnectors.framework.common.objects.ConnectorObject;
import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
import org.identityconnectors.framework.common.objects.ObjectClass;
import org.identityconnectors.framework.common.objects.OperationOptions;
import org.identityconnectors.framework.common.objects.ResultsHandler;
import org.identityconnectors.framework.common.objects.Schema;
import org.identityconnectors.framework.common.objects.SchemaBuilder;
import org.identityconnectors.framework.common.objects.Uid;
import org.identityconnectors.framework.common.objects.filter.AbstractFilterTranslator;
import org.identityconnectors.framework.common.objects.filter.FilterTranslator;
import org.identityconnectors.framework.spi.Configuration;
import org.identityconnectors.framework.spi.ConnectorClass;
import org.identityconnectors.framework.spi.PoolableConnector;
import org.identityconnectors.framework.spi.operations.CreateOp;
import org.identityconnectors.framework.spi.operations.DeleteOp;
import org.identityconnectors.framework.spi.operations.SchemaOp;
import org.identityconnectors.framework.spi.operations.SearchOp;
import org.identityconnectors.framework.spi.operations.UpdateOp;
/**
* The main connector class
*/
@ConnectorClass(configurationClass = FlatFileConfiguration.class, displayNameKey = "FlatFile")
public class FlatFileConnector implements SchemaOp, CreateOp, DeleteOp,
UpdateOp, SearchOp<Map<String, String>>, GetApiOp, PoolableConnector {
private FlatFileConfiguration flatFileConfig;
private FlatFileMetadata flatFileMetadata;
private FlatFileParser flatFileParser;
private FlatFileWriter flatFileWriter;
private boolean alive = false;
@Override
public Configuration getConfiguration() {
return this.flatFileConfig;
}
@Override
public void init(Configuration config) {
this.flatFileConfig = (FlatFileConfiguration) config;
FlatFileIOFactory flatFileIOFactory =
FlatFileIOFactory.getInstance(flatFileConfig);
this.flatFileMetadata = flatFileIOFactory.getMetadataInstance();
this.flatFileParser = flatFileIOFactory.getFileParserInstance();
this.flatFileWriter = flatFileIOFactory.getFileWriterInstance();
this.alive = true;
System.out.println("init called: Initialization done");
}
@Override
public void dispose() {
this.alive = false;
}
@Override
public Schema schema() {
SchemaBuilder flatFileSchemaBldr = new SchemaBuilder(this.getClass());
Set<AttributeInfo> attrInfos = new HashSet<AttributeInfo>();
for (String fieldName : flatFileMetadata.getOrderedTextFieldNames()) {
AttributeInfoBuilder attrBuilder = new AttributeInfoBuilder();
attrBuilder.setName(fieldName);
attrBuilder.setCreateable(true);
attrBuilder.setUpdateable(true);
attrInfos.add(attrBuilder.build());
}
// Supported class and attributes
flatFileSchemaBldr.defineObjectClass
(ObjectClass.ACCOUNT.getDisplayNameKey(),attrInfos);
System.out.println("schema called: Built the schema properly");
return flatFileSchemaBldr.build();
}
@Override
public Uid create(ObjectClass arg0, Set<Attribute> attrs,
OperationOptions ops) {
System.out.println("Creating user account " + attrs);
assertUserObjectClass(arg0);
try {
FlatFileUserAccount accountRecord = new FlatFileUserAccount(attrs);
// Assert uid is there
assertUidPresence(accountRecord);
// Create the user
this.flatFileWriter.addAccount(accountRecord);
// Return uid
String uniqueAttrField = this.flatFileConfig
.getUniqueAttributeName();
String uniqueAttrVal = accountRecord
.getAttributeValue(uniqueAttrField);
System.out.println("User " + uniqueAttrVal + " created");
return new Uid(uniqueAttrVal);
} catch (Exception ex) {
// If account exists
if (ex.getMessage().contains("exists"))
throw new AlreadyExistsException(ex);
// For all other causes
System.out.println("Error in create " + ex.getMessage());
throw ConnectorException.wrap(ex);
}
}
@Override
public void delete(ObjectClass arg0, Uid arg1, OperationOptions arg2) {
final String uidVal = arg1.getUidValue();
this.flatFileWriter.deleteAccount(uidVal);
System.out.println("Account " + uidVal + " deleted");
}
@Override
public Uid update(ObjectClass arg0, Uid arg1, Set<Attribute> arg2,
OperationOptions arg3) {
String accountIdentifier = arg1.getUidValue();
// Fetch the account
FlatFileUserAccount accountToBeUpdated = this.flatFileParser
.getAccount(accountIdentifier);
// Update
accountToBeUpdated.updateAttributes(arg2);
this.flatFileWriter
.modifyAccount(accountIdentifier, accountToBeUpdated);
System.out.println("Account " + accountIdentifier + " updated");
// Return new uid
String newAccountIdentifier = accountToBeUpdated
.getAttributeValue(this.flatFileConfig.getUniqueAttributeName());
return new Uid(newAccountIdentifier);
}
@Override
public FilterTranslator<Map<String, String>> createFilterTranslator(
ObjectClass arg0, OperationOptions arg1) {
// TODO: Create a fine grained filter translator
// Return a dummy object as its not applicable here.
// All processing happens in the execute query
return new AbstractFilterTranslator<Map<String, String>>() {
};
}
@Override
public ConnectorObject getObject(ObjectClass arg0, Uid uid,
OperationOptions arg2) {
// Return matching record
String accountIdentifier = uid.getUidValue();
FlatFileUserAccount userAcc = this.flatFileParser
.getAccount(accountIdentifier);
ConnectorObject userAccConnObject = convertToConnectorObject(userAcc);
return userAccConnObject;
}
/*
* (non-Javadoc)
* This is the search implementation.
* The Map passed as the query here, will map to all the records with
* matching attributes.
*
* The record will be filtered if any of the matching attributes are not
* found
*
* @see
* org.identityconnectors.framework.spi.operations.SearchOp#executeQuery
* (org.identityconnectors.framework.common.objects.ObjectClass,
* java.lang.Object,
* org.identityconnectors.framework.common.objects.ResultsHandler,
* org.identityconnectors.framework.common.objects.OperationOptions)
*/
@Override
public void executeQuery(ObjectClass objectClass,
Map<String, String> matchSet, ResultsHandler resultHandler,
OperationOptions ops) {
System.out.println("Inside executeQuery");
// Iterate over the records and handle individually
Iterator<FlatFileUserAccount> userAccountIterator = this.flatFileParser
.getAccountIterator(matchSet);
while (userAccountIterator.hasNext()) {
FlatFileUserAccount userAcc = userAccountIterator.next();
ConnectorObject userAccObject = convertToConnectorObject(userAcc);
if (!resultHandler.handle(userAccObject)) {
System.out.println("Not able to handle " + userAcc);
break;
}
}
}
private void assertUserObjectClass(ObjectClass arg0) {
if (!arg0.equals(ObjectClass.ACCOUNT))
throw new UnsupportedOperationException(
"Only user account operations supported.");
}
private void assertUidPresence(FlatFileUserAccount accountRecord) {
String uniqueAttrField = this.flatFileConfig.getUniqueAttributeName();
String uniqueAttrVal = accountRecord.getAttributeValue(uniqueAttrField);
if (uniqueAttrVal == null) {
throw new IllegalArgumentException("Unique attribute not passed");
}
}
private ConnectorObject convertToConnectorObject(FlatFileUserAccount userAcc) {
ConnectorObjectBuilder userObjBuilder = new ConnectorObjectBuilder();
// Add attributes
List<String> attributeNames = this.flatFileMetadata
.getOrderedTextFieldNames();
for (String attributeName : attributeNames) {
String attributeVal = userAcc.getAttributeValue(attributeName);
userObjBuilder.addAttribute(attributeName, attributeVal);
if (attributeName.equals(this.flatFileConfig
.getUniqueAttributeName())) {
userObjBuilder.setUid(attributeVal);
userObjBuilder.setName(attributeVal);
}
}
return userObjBuilder.build();
}
@Override
public void checkAlive() {
if (!alive)
throw new RuntimeException("Connection not alive");
}
}
This BLOG focuses on "hands on approach" around AWS, OCI Oracle Cloud Infrastructure, Dev/Ops, MicroServices, OKTA, Oracle Fusion Middleware, Oracle Service Bus, Oracle AIA, Oracle SOA Suite, Oracle SOA Cloud/Developer Cloud, Oracle Identity Management including OID, OAM, OIM, OSSO, Oracle Big Data, WLST Scripts and Oracle Edifecs B2B Engine for HIPAA/HL7/X12/EDIFACT EDI., Kafka, Spark, Spring Boot, DevOps, AWS, GCP and Oracle Cloud
Amazon Bedrock and AWS Rekognition comparison for Image Recognition
Both Amazon Bedrock and AWS Rekognition are services provided by AWS, but they cater to different use cases, especially when it comes to ...
-
Oracle Service Bus 11g 11.1.1.8 : How to export an OSB project from OSB console and import it in OEPE 1.) On the Right Hand Side pane, sel...
-
Oracle Cloud Infrastructure (OCI) provides a comprehensive set of infrastructure services that enable you to build and run a wide range of...
-
Kafka is a publish-subscribe messaging system that provides a reliable Spark Streaming source. The Kafka project introduced a new consumer...