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

Popular posts from this blog

D2 install

Arch Flow