You can add support that allows people to filter listed instances of your content type. With this support, people can filter instances by user, creation date, and modification date.

Note: The code in this topic is from the Memo sample content type. You'll find the sample in the Jive public sample Subversion repository. The content in this topic assumes you've implemented a manager class to locate content type instances based on their ID in the system.

Note: The content type API is still a new feature that might change as developers provide feedback about it.

Here are the high-level steps. You'll find more about each in the sections below.

Provide Information About Filtering Support

Implement the FilteredContentProvider interface to describe how your content type supports filtering. Most of your implementation's work will be to return the SQL statement that queries for instances based on filter parameters. You'll do that in the getFilteredContentQuery method, where you'll receive the parameters and insert them into the SQL statement you build.

The following example is from the memo sample.

/**
* Provides information on the memo content type's support for filtering
* lists of content in the user interface. This class translates filter parameters
* set by the user into an SQL query designed to return a list of memo
* instances constrained by the parameters.
*/
public class MemoFilteredContentProvider implements FilteredContentProvider {

    // Field and accessors for the CommunityManager instance
    // injected by Spring.
    private ExtendedCommunityManager communityManager;  
    public void setCommunityManager(ExtendedCommunityManager communityManager) {
        this.communityManager = communityManager;
    }
    public ExtendedCommunityManager getCommunityManager() {
        return communityManager;
    }

    // Code follows.

}

/**
* Gets the query for filtering content, based on the context defined through values
* in the parameter list. This method instantiates a QueryContainer by building a SQL
* statement and adding statement argument values along the way. This makes it
* possible to build the statement's clauses conditionally based on the context
* values received as parameters. The resulting SQL statement must be designed to
* return four columns: objectID, objectType, modDate, and createDate. Those will be
* used to display the list of content.
*
* @param contentListFilter Parameters for filtering.
* @param targetContainer The container in which the filter will be created.
* @param isContainerRoot true if the container is the root; false if it isn't.
* @return The generated query.
*/
public QueryContainer getFilteredContentQuery(ResultFilter contentListFilter,

    JiveContainer targetContainer, boolean isContainerRoot)
{
    // Find out if the user requested to filter by user, creation date range or modified date
    // range. If so, assign those values to variables. Those that have been specified
    // will be used later to build the SQL statement.
    boolean filterUser = contentListFilter.getUserID() != ResultFilter.NULL_INT;
    boolean filterCreationDate = contentListFilter.getCreationDateRangeMin() != null
            || contentListFilter.getCreationDateRangeMax() != null;
    boolean filterModifiedDate = contentListFilter.getModificationDateRangeMin() != null
            || contentListFilter.getModificationDateRangeMax() != null;

    // The container that will hold the SQL statement and parameters.
    QueryContainer query = new QueryContainer();

    // Start by selecting the columns that must be included in the returned
    // QueryContainer instance: objectID, objectType, modDate, and createDate.
    query.appendText("SELECT DISTINCT jiveMemo.memoID as objectID, ");
    query.appendText(String.valueOf(MemoObjectType.MEMO_TYPE_ID));
    query.appendText(" as objectType, jiveMemo.modificationDate as modDate,");
    query.appendText(" jiveMemo.creationDate as createDate");

    // Select from the content type's instance table.
    query.appendText(" FROM jiveMemo");

    //
    if (!isContainerRoot && contentListFilter.isRecursive()
            && targetContainer.getObjectType() == JiveConstants.COMMUNITY)
    {
        query.appendText(", jiveCommunity");
    }
  
    // Append an innocuous WHERE clause that will work for appending AND clauses,
    // yet will work even if no AND clauses are appended.
    query.appendText(" WHERE 1=1");
  
    // If the current context isn't the root space, add clauses that constrain the
    // query for a sub-space.
    if (!isContainerRoot) {
        // If the filter is recursive and the filter container is a space,
        // specify this in the statement, along with left and right values.
        if (contentListFilter.isRecursive() && targetContainer.getObjectType()

                == JiveConstants.COMMUNITY) {
            query.appendText(" AND jiveMemo.containerType = ?");
            query.addArgumentValue(JiveConstants.COMMUNITY);
            query.appendText(" AND jiveMemo.containerID = jiveCommunity.communityID");
            int[] lftRgtValues = getCommunityManager().getLftRgtValues(targetContainer.getID());
            query.appendText(" AND jiveCommunity.lft >= ?");
            query.addArgumentValue(lftRgtValues[0]);
            query.appendText(" AND jiveCommunity.rgt <= ?");
            query.addArgumentValue(lftRgtValues[1]);
        }
        // Otherwise simply specify targetContainer type and ID.
        else {
            query.appendText(" AND jiveMemo.containerType = ?");
            query.addArgumentValue(targetContainer.getObjectType());
            query.appendText(" AND jiveMemo.containerID = ?");
            query.addArgumentValue(targetContainer.getID());
        }
    }

    // If the filter parameters specify a user to filter by, append their ID
    // as a query parameter.
    if (filterUser) {
        query.appendText(" AND jiveMemo.userID = ?");
        query.addArgumentValue(contentListFilter.getUserID());
    }

    // If filter parameters specify a creation date range, append those parameters
    // to the SQL statement.
    if (filterCreationDate) {
        if (contentListFilter.getCreationDateRangeMin() != null) {
            query.appendText(" AND jiveMemo.creationDate >= ?");
            query.addArgumentValue(contentListFilter.getCreationDateRangeMin().getTime());
        }
        if (contentListFilter.getCreationDateRangeMax() != null) {
            query.appendText(" AND jiveMemo.creationDate <= ?");
            query.addArgumentValue(contentListFilter.getCreationDateRangeMax().getTime());
        }
    }

    // If filter parameters specify a modification date range, append
    // the range to the query.
    if (filterModifiedDate) {
        if (contentListFilter.getModificationDateRangeMin() != null) {
            query.appendText(" AND jiveMemo.modificationDate >= ?");
            query.addArgumentValue(contentListFilter.getModificationDateRangeMin().getTime());
        }
        if (contentListFilter.getModificationDateRangeMax() != null) {
            query.appendText(" AND jiveMemo.modificationDate <= ?");
            query.addArgumentValue(contentListFilter.getModificationDateRangeMax().getTime());
        }
    }
    return query;
}

<bean id="memoFilteredContentProvider" class="com.jivesoftware.clearspace.plugin.test_dynamic.MemoFilteredContentProvider">
    <property name="communityManager" ref="communityManagerImpl"/>
</bean>

Signal Support for Filtering

You can declare your content type's support for filtering by implementing the FilteredContentEnabledType, whose single method returns the info provider you've created.

public class MemoObjectType implements FilteredContentEnabledType
{

    // Field and accessors for Spring injection and method required

    // when implementing the interface.

    private FilteredContentProvider filteredContentProvider;

    public FilteredContentProvider getFilteredContentProvider() {
        return filteredContentProvider;
    }
    public void setFilteredContentProvider(FilteredContentProvider filteredContentProvider) {
        this.filteredContentProvider = filteredContentProvider;
    }

    // Code omitted.
}

<bean id="memoObjectType" class="com.jivesoftware.clearspace.plugin.test_dynamic.MemoObjectType">
    <property name="filteredContentProvider" ref="memoFilteredContentProvider"/>
</bean>