Catalog Metadata Based Tagging

Introduction

Many customers have expressed the requirement of filtering catalog searches based on Catalog Item’s Metadata (CIM) including User Defined Fields (UDFs) added to the Catalog’s schema. Whereas this functionality is not offered out of the box by OIM 11g, it can be achieved in a relatively easy manner via custom code and UI customizations. This article will discuss the details of the API’s that can be used to retrieve the metadata from a Catalog Item and set the user defined tags value accordingly, so a search in the catalog’s UI will retrieve results filtered by the Metadata. This sample code can then be called from a Managed Bean that can be used as part of a User Interface Customization, which is not part of the scope of this article.

 

Main Article

The functionality presented here includes the following capabilities:

  • Search for Catalog Items based on Category and a string filter
  • Search for all Catalog Items matching a string filter
  • Update the metadata of individual Catalog Items
  • Tag one or multiple Catalog Items using their metadata

The implementation is comprised mainly of two classes:

CatalogServiceWrapper: This class contains an instance of the CatalogService and it is used to call Catalog APIs. This class only works when invoked inside a Managed Bean deployed within the customization library of OIM. Calling this class outside OIM’s authenticated sessions will not work.

CatalogMetadataWrapper: This is a convenience class that can be used to populate lists or tables in ADF based UIs, like a custom task flow that can be invoked within OIM’s Self Service Console. This class wraps MetaData instances coming from Catalog Items, which represent the item’s metadata fields. It is also used to update individual metadata fields in a Catalog Item’s Metadata. Here is the implementation of this class for your reference:

package com.ateam.custom.samples.model;

import java.io.Serializable;
import oracle.iam.catalog.vo.MetaData;
import oracle.iam.catalog.vo.MetaDataDefinition;

public class CatalogMetadataWrapper implements Serializable {
  @SuppressWarnings("compatibility:576973872673041719")
  private static final long serialVersionUID = 1L;
  private MetaData itemMetaData;
    
    public CatalogMetadataWrapper() {
        super();
    }
  
    public void setItemMetaData(MetaData itemMetaData) {
        this.itemMetaData = itemMetaData;
    }
    
    public String getDisplayName() {
        return this.itemMetaData.getMetaDataDefinition().getDisplayName();
    }
    
    public MetaDataDefinition.Type getValueType() {
        return this.itemMetaData.getMetaDataDefinition().getDataType();  
    }
    
    public long getFieldID() {
        return this.itemMetaData.getMetaDataDefinition().getId();
    }
    
    public String getValue() {
        return this.itemMetaData.getValue();
    }
    
    public void setValue(String value) {
        this.itemMetaData.setValue(value);
    }
    
    public MetaData retrieveMetadata() {
        return this.itemMetaData;
    }
}

Search Catalog Items

There are four methods in the CatalogServiceWrapper class that provide searching functionality. These are:

  • getApplicationInstances
  • getRolesInCatalog
  • getEntitlementsInCatalog
  • getAllCatalogItems

All four methods receive a parameter which is a string containing a filter. See the figures below for the implementation of all four methods:

    public List<Catalog> getApplicationInstances(String filter) {
        CatalogSearchCriteria tags = new CatalogSearchCriteria(CatalogSearchCriteria.Argument.TAG, filter, CatalogSearchCriteria.Operator.EQUAL);
        CatalogSearchCriteria cat = new CatalogSearchCriteria(CatalogSearchCriteria.Argument.CATEGORY, "ApplicationInstance", CatalogSearchCriteria.Operator.EQUAL);
        CatalogSearchCriteria scrt = new CatalogSearchCriteria(tags, cat, CatalogSearchCriteria.Operator.AND);

        try {
            return catalogService.search(scrt, 0, 10, CatalogConstants.CATALOG_CATEGORY, CatalogSearchCriteria.SortCriteria.ASCENDING).getCatalogs();
        } 
        catch (CatalogException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e);
        }
    }
  
    public List<Catalog> getRolesInCatalog(String filter) {
        CatalogSearchCriteria tags = new CatalogSearchCriteria(CatalogSearchCriteria.Argument.TAG, filter, CatalogSearchCriteria.Operator.EQUAL);
        CatalogSearchCriteria cat = new CatalogSearchCriteria(CatalogSearchCriteria.Argument.CATEGORY, "Role", CatalogSearchCriteria.Operator.EQUAL);
        CatalogSearchCriteria scrt = new CatalogSearchCriteria(tags, cat, CatalogSearchCriteria.Operator.AND);
        try {
            return catalogService.search(scrt, 0, 10, CatalogConstants.CATALOG_CATEGORY, CatalogSearchCriteria.SortCriteria.ASCENDING).getCatalogs();
        } 
        catch (CatalogException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e);
        }
    }
    
    public List<Catalog> getEntitlementsInCatalog(String filter) {
        CatalogSearchCriteria tags = new CatalogSearchCriteria(CatalogSearchCriteria.Argument.TAG, filter, CatalogSearchCriteria.Operator.EQUAL);
        CatalogSearchCriteria cat = new CatalogSearchCriteria(CatalogSearchCriteria.Argument.CATEGORY, "Entitlement", CatalogSearchCriteria.Operator.EQUAL);
        CatalogSearchCriteria scrt = new CatalogSearchCriteria(tags, cat, CatalogSearchCriteria.Operator.AND);
        try {
            return catalogService.search(scrt, 0, 10, CatalogConstants.CATALOG_CATEGORY, CatalogSearchCriteria.SortCriteria.ASCENDING).getCatalogs();
        } 
        catch (CatalogException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e);
        }
    }
    
    public List<Catalog> getAllCatalogItems(String filter) {
        List<Catalog> consolidated = this.getApplicationInstances(filter);
        consolidated.addAll(this.getRolesInCatalog(filter));
        consolidated.addAll(this.getEntitlementsInCatalog(filter));
        return consolidated;  
    }

Update Catalog Item’s Metadata

In CatalogServiceWrapper, the method updateMetadata is provided to update the values of metadata fields of a single catalog item. This method receives two parameters: the item whose metadata is to be updated and the instance of CatalogMetadataWrapper containing the metadata field to be updated. The implementation of this method is presented below:

    public void updateMetadata(Catalog item, CatalogMetadataWrapper md) {
        List<MetaData> currentMD = item.getMetadata();
        Iterator<MetaData> iter = currentMD.iterator();
        while (iter.hasNext()) {
            MetaData currentField = iter.next();
            MetaData compareWith = md.retrieveMetadata();
            if (currentField.getMetaDataDefinition().getId() == compareWith.getMetaDataDefinition().getId()) {
                currentField.setValue(md.getValue());
                Result res;
                try {
                    res = this.catalogService.updateCatalogItems(item);
                    return;
                } catch (CatalogException e) {
                    e.printStackTrace();
                    throw new RuntimeException(res.getException().getMessage(), res.getException().getCause());
                }
            }
        }
    }

Tagging

Finally, the CatalogServiceWrapper implements the tagging functionality in two methods; one method tags individual items and the other tags multiple items by calling the first method within a loop iterating through a list of Catalog Items passed as a parameter.

    public void tagCatalogItem(Catalog item) {
        StringBuffer tagsValue = new StringBuffer();
        
        List<MetaData> itemMD = item.getMetadata();
        Iterator<MetaData> iter = itemMD.iterator();
        while (iter.hasNext()) {
            MetaData md = iter.next();
            String value = md.getValue();
            if (value != null && !value.equals("")) {
                tagsValue.append(value);
            }
            if (iter.hasNext()) {
                tagsValue.append(" ");
            }
        }
        item.setUserDefinedTags(tagsValue.toString());
        try {
            this.catalogService.updateCatalogItems(item);
        } catch (CatalogException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e);
        }
    }

The method above simply iterates through all the metadata fields (MetaData) extracted from the item (Catalog) passed as a parameter, and builds a string containing all the non-null values of the metadata fields. After building the string containing all metadata field values, the string is set as the user defined tags value of the item.

The following method tags multiple Catalog items placed in a list by invoking the method previously described.

    public void tagPoolItems(List<Catalog> pool) {
        Iterator<Catalog> iter = pool.iterator();
        while (iter.hasNext()) {
            Catalog item = iter.next();
            this.tagCatalogItem(item);
        }
    }

Summary

This article presented a sample implementation of basic tagging based on the values of Catalog Item Metadata fields. After the individual items are tagged, the out of the box search functionality can be used to search for catalog items filtered by metadata values.

This implementation can be integrated into a UI customization to provide administrators (i.e. Catalog Administrators) with the ability to tag all the catalog items so users can filter searches based on Catalog metadata fields.

Add Your Comment