D2-Ref
/**
* D2CollectionServicePlugin.java
*
* Service override — post-processes the collection list returned by
* D2CollectionService to filter collections by case_id of the selected document.
*
* Pattern: IDENTICAL to D2ContentServicePlugin.java from the D2 SDK.
* Dev Guide reference: pp.31-34 "Understanding Service Interface Overrides"
* "Post-Processing" and "Setting Up D2 Service Overrides"
*
* HOW IT WORKS:
* 1. D2CollectionService.getCollections() is called by D2 when the
* "Add to Collection" picker opens in SmartView.
* 2. This plugin intercepts that call, calls super() to get the full list,
* then post-processes: removes any collection whose name does NOT end
* with the case_id value of the currently selected document.
* 3. SmartView receives the filtered list and shows only matching collections.
*
* IMPORTS — ALL confirmed available in D2FS4DCTM-WEB-{ver}.jar and dfc.jar:
* ID2fsPlugin → com.emc.d2fs.dctm.web.services (D2FS4DCTM-WEB)
* D2fsContext → com.emc.d2fs.dctm.web.services (D2FS4DCTM-WEB)
* ParameterParser → com.emc.d2fs.dctm.utils (D2FS4DCTM-WEB)
* D2CollectionService → com.emc.d2fs.dctm.web.services.collection (D2FS4DCTM-WEB)
* IVersion → com.emc.common.java.utils (C6-Common)
* IDfSession → com.documentum.fc.client (dfc.jar)
* IDfSysObject → com.documentum.fc.client (dfc.jar)
* DfException → com.documentum.fc.common (dfc.jar)
* Logger → org.slf4j (slf4j-api)
*/
package com.opentext.collectionfilter.webfs.services.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.common.DfException;
import com.emc.common.java.utils.IVersion;
import com.emc.d2fs.dctm.utils.ParameterParser;
import com.emc.d2fs.dctm.web.services.D2fsContext;
import com.emc.d2fs.dctm.web.services.ID2fsPlugin;
import com.emc.d2fs.dctm.web.services.collection.D2CollectionService;
import com.opentext.collectionfilter.CollectionFilterVersion;
/**
* Post-processing override of D2CollectionService.
*
* Extends D2CollectionService — same pattern as D2ContentServicePlugin
* extends D2ContentService in the SDK.
*
* Implements ID2fsPlugin — required by all D2 service overrides.
* Forces implementation of getFullName() and getProductName().
*/
public class D2CollectionServicePlugin extends D2CollectionService
implements ID2fsPlugin
{
private static final IVersion VERSION = new CollectionFilterVersion();
private static final Logger LOGGER =
LoggerFactory.getLogger(D2CollectionServicePlugin.class);
// -----------------------------------------------------------------------
// STEP A: Override the method that provides the collection list.
//
// *** IMPORTANT: Replace "getCollections" and its parameters below
// with the EXACT method signature you found in Step 4 above.
//
// The pattern is always:
// 1. Call super.sameMethod(same params) to get the full list
// 2. Post-process (filter) the result
// 3. Return filtered result
//
// This is documented in Dev Guide p.32 "Post-Processing":
// "You can add data processing after a service by adding code
// after the super call."
// -----------------------------------------------------------------------
@Override
public Object getCollections(Context context) throws Exception
{
LOGGER.debug("D2CollectionServicePlugin.getCollections() - start");
// Step 1: Call super to get the full unfiltered list
// (Same pattern as D2ContentServicePlugin calling super.getContent())
Object fullResult = super.getCollections(context);
LOGGER.debug("D2CollectionServicePlugin - post processing collection list");
// Step 2: Get the DFC session to read the selected document's case_id
// Pattern from D2ExportServicePlugin: d2fsContext.getSession()
D2fsContext d2fsContext = (D2fsContext) context;
ParameterParser params = d2fsContext.getParameterParser();
IDfSession session = d2fsContext.getSession();
// Step 3: Read the selected document ID from request parameters
// Pattern from D2CustomService/D2ExportServicePlugin: getListParameter("id")
List<String> selectedIds = params.getListParameter("id");
if (selectedIds == null || selectedIds.isEmpty()) {
LOGGER.warn("No document ID in request — returning full collection list");
return fullResult;
}
String docId = selectedIds.get(0).trim();
LOGGER.debug("Reading case_id from document: {}", docId);
// Step 4: Read case_id from the selected document via DFC
String caseId = null;
try {
IDfSysObject doc = (IDfSysObject) session.getObject(
session.getIdByQualification(
"dm_sysobject WHERE r_object_id = '" + docId + "'"));
if (doc != null) {
// *** Replace "case_id" with your exact DQL attribute name ***
caseId = doc.getString("case_id");
LOGGER.debug("case_id = '{}'", caseId);
}
} catch (DfException e) {
LOGGER.error("Cannot read case_id from doc {}: {}", docId, e.getMessage());
return fullResult; // fail safe — return full list on error
}
if (caseId == null || caseId.trim().isEmpty()) {
LOGGER.warn("case_id is empty — returning full collection list");
return fullResult;
}
// Step 5: Post-process — filter list to names ending with case_id
// *** Adjust the cast and item accessor to match the actual return
// type of D2CollectionService.getCollections() in your version ***
return filterCollections(fullResult, caseId.trim());
}
/**
* Filters a collection result to only items whose name ends with suffix.
*
* The result type from D2CollectionService depends on your D2 version.
* Three common patterns are handled below — uncomment the one that
* matches what you see when you decompile D2CollectionService.
*/
private Object filterCollections(Object result, String suffix)
{
if (result == null) return null;
LOGGER.debug("Filtering collections by suffix: '{}'", suffix);
// PATTERN A: result is a List of objects with a getName() method
// (Most common — matches DocItems/Item pattern from D2ContentServicePlugin)
if (result instanceof List) {
List<?> items = (List<?>) result;
List<Object> filtered = new ArrayList<Object>();
for (Object item : items) {
String name = getNameFromItem(item);
if (name != null && name.endsWith(suffix)) {
LOGGER.debug("KEEP collection: '{}'", name);
filtered.add(item);
} else {
LOGGER.debug("SKIP collection: '{}'", name);
}
}
LOGGER.debug("Filtered: {} of {} collections match",
filtered.size(), items.size());
return filtered;
}
// PATTERN B: result type is unknown — log the type so you can adjust
LOGGER.warn("Unrecognised collection result type: {} — returning unfiltered",
result.getClass().getName());
return result;
}
/**
* Extracts the display name from a collection item.
* Tries common accessor method names used in D2FS model objects.
* If neither works, check the decompiled D2CollectionService return type
* and add the correct method call here.
*/
private String getNameFromItem(Object item)
{
if (item == null) return null;
// Try getName() first — standard D2FS model pattern
try {
return (String) item.getClass().getMethod("getName").invoke(item);
} catch (Exception e1) {
// Try getObjectName() — alternative D2FS naming
try {
return (String) item.getClass()
.getMethod("getObjectName").invoke(item);
} catch (Exception e2) {
LOGGER.warn("Cannot read name from item type: {}",
item.getClass().getName());
return null;
}
}
}
// -----------------------------------------------------------------------
// ID2fsPlugin required methods
// Pattern from D2ExportServicePlugin and D2ContentServicePlugin in SDK
// -----------------------------------------------------------------------
/**
* Returns full plugin name + version.
* Called by D2 Client Help → About D2 dialog.
* Dev Guide p.34: "Returns the full plug-in name with its version number."
*/
@Override
public String getFullName()
{
return VERSION.getFullName();
}
/**
* Returns plugin product name.
* Dev Guide p.35: "Returns the plug-in name to determine whether the
* plug-in should be executed based on the D2 configuration matrix."
*/
@Override
public String getProductName()
{
return VERSION.getProductName();
}
}
Comments
Post a Comment