Search

We will present here a simple example of how to define a search form.

Configuration

The configuration of a search is done in 2 parts:

  • definition of the search criteria.
  • definition of the presentation of the search results.

Definition of search criteria

First we need to define the target indexes for the search. This happens in the sourceIndexes attribute of the search tag.

Now we can define the list of fields (customtag) that will compose our search form. The customtag of the search can only be those that are present in the source indexes.

As presented in the customtag documentation, we can define on a customtag a custom graphical control. This allows us to customize the filtering system.

Auto-suggestion control on the values of a customtag :

  • This control will allow an auto-suggestion on a free input. It is between a free input and a list; the user starts typing a filtering element and the system guides him by proposing possible values for this customtag (corresponding to the beginning of the input).
  • On your customtag, you can simply add a “customControl” pointing to “com.axemble.axvdocsearch.ui.core.document.fields.TextBoxAutoCompleteField” : <customtag name="Champliste" type="text" label="LG_Champliste" operators="contents" customControl="com.axemble.axvdocsearch.ui.core.document.fields.TextBoxAutoCompleteField" />
Info

We can add the attribute “operators” which allows us to assign the filter operator and hide the list.

Definition of the presentation of research results

In a second step we need to define our search result (list of columns to display).

So we will define a view that will contain columns. The name of the columns must be one of the customtag.

Info

The result row will be built in the defined column order.

Example

<searches>
	<search name="caseBasicSearch"
		label="LG_caseBasicSearch" 
		sourceIndexes="IndexProcess" 
		extension="" 
		securityExtension="com.axemble.axvdocsearch.extensions.implementation.ISecurityExtension.VDocSecurityExtension" 
		fullTextInput="true" 
		defaultViewRowsPerPage="10" 
		autoExecuteSearch="false"
		linkable="true" >
			
		<customtag name="Champtexte" type="text" label="LG_Champtexte" />
		<customtag name="Champnombre" type="number" label="LG_Champnombre" />
		<customtag name="Champdate" type="date" label="LG_Champdate" />
		<customtag name="Champlistesimple" type="text" label="LG_Champlistesimple" list="true" />
		<customtag name="Champlistemultiple" type="text" collection="true" label="LG_Champlistemultiple" list="true" multipleSearch="true" />
		<customtag name="Champlistedepersonnessimple" type="text" label="LG_Champlistedepersonnessimple" list="true" />
		<customtag name="Champlistedepersonnesmultiple" type="text" collection="true" label="LG_Champlistedepersonnesmultiple" list="true" multipleSearch="true" multipleSearchMode="list" />
		<customtag name="Champrolesimple" type="text" label="LG_Champrolesimple" />
		<customtag name="Champrolemultiple" type="text" collection="true" label="LG_Champrolemultiple" list="true" multipleSearch="true" />
		
		<view linksTarget="_blank" toolTips="REFERENCE" >
			<column name="CREATIONDATE" label="LG_CREATIONDATE" type="date" />
			<column name="Champtexte" type="text" label="LG_Champtexte" />
			<column name="Champnombre" type="number" label="LG_Champnombre" />
			<column name="Champdate" type="date" label="LG_Champdate" />
			<column name="Champlistesimple" type="text" label="LG_Champlistesimple" />
			<column name="Champlistemultiple" type="text" label="LG_Champlistemultiple" collection="true" />
			<column name="Champlistedepersonnessimple" type="text" label="LG_Champlistedepersonnessimple" />
			<column name="Champlistedepersonnesmultiple" type="text" label="LG_Champlistedepersonnesmultiple" collection="true" />
			<column name="Champrolesimple" type="text" label="LG_Champrolesimple" />
			<column name="Champrolemultiple" type="text" label="LG_Champrolemultiple" collection="true"/>
		</view>
	</search>
</searches>
<searches>
	<search name="caseBasicSearch"
		label="LG_caseBasicSearch" 
		sourceIndexes="IndexProcess" 
		extension="" 
		securityExtension="com.axemble.axvdocsearch.extensions.implementation.security.VDocSecurityExtension" 
		fullTextInput="true" 
		defaultViewRowsPerPage="10" 
		autoExecuteSearch="false"
		linkable="true" >
			
		<customtag name="Champtexte" type="text" label="LG_Champtexte" />
		<customtag name="Champnombre" type="number" label="LG_Champnombre" />
		<customtag name="Champdate" type="date" label="LG_Champdate" />
		<customtag name="Champlistesimple" type="text" label="LG_Champlistesimple" list="true" />
		<customtag name="Champlistemultiple" type="text" collection="true" label="LG_Champlistemultiple" list="true" multipleSearch="true" />
		<customtag name="Champlistedepersonnessimple" type="text" label="LG_Champlistedepersonnessimple" list="true" />
		<customtag name="Champlistedepersonnesmultiple" type="text" collection="true" label="LG_Champlistedepersonnesmultiple" list="true" multipleSearch="true" multipleSearchMode="list" />
		<customtag name="Champrolesimple" type="text" label="LG_Champrolesimple" />
		<customtag name="Champrolemultiple" type="text" collection="true" label="LG_Champrolemultiple" list="true" multipleSearch="true" />
		
		<view linksTarget="_blank" toolTips="REFERENCE" >
			<column name="CREATIONDATE" label="LG_CREATIONDATE" type="date" />
			<column name="Champtexte" type="text" label="LG_Champtexte" />
			<column name="Champnombre" type="number" label="LG_Champnombre" />
			<column name="Champdate" type="date" label="LG_Champdate" />
			<column name="Champlistesimple" type="text" label="LG_Champlistesimple" />
			<column name="Champlistemultiple" type="text" label="LG_Champlistemultiple" collection="true" />
			<column name="Champlistedepersonnessimple" type="text" label="LG_Champlistedepersonnessimple" />
			<column name="Champlistedepersonnesmultiple" type="text" label="LG_Champlistedepersonnesmultiple" collection="true" />
			<column name="Champrolesimple" type="text" label="LG_Champrolesimple" />
			<column name="Champrolemultiple" type="text" label="LG_Champrolemultiple" collection="true"/>
		</view>
	</search>
</searches>

Source : https://wiki.myvdoc.net/xwiki/bin/view/Dev+Floor/MyFirstSearch

Data security

Note

By default, an Xtended Search presents the search results without security tests against the logged-in user.

On the other hand, it is obviously possible to secure the access to the data:

  • By reproducing the Process security
  • By creating our own specific security (see here)

Declaration of a security extension class

It is possible to declare a security extension class on your search, in the XML, in a “securityExtension” attribute.

<search ... securityExtension="com.axemble.axvdocsearch.extensions.implementation.ISecurityExtension.VDocSecurityExtension" ... >
...
</search>
<search ... securityExtension="com.axemble.axvdocsearch.extensions.implementation.security.VDocSecurityExtension" ... >
...
</search>

Standard security classes

  • For all modules except GED : com.axemble.axvdocsearch.extensions.implementation.ISecurityExtension.VDocSecurityExtension
  • For the GED module, Document Management : com.axemble.axvdocsearch.extensions.implementation.ISecurityExtension.VDocDocumentManagementSecurityExtension
  • For all modules except GED : com.axemble.axvdocsearch.extensions.implementation.security.VDocSecurityExtension
  • For the GED module, Document Management : com.axemble.axvdocsearch.extensions.implementation.security.VDocDocumentManagementSecurityExtension

Source : https://wiki.myvdoc.net/xwiki/bin/view/Dev+Floor/MySecuredFirstSearch

Filtergroup

It is possible to enter “hidden” search criteria for the end user. This way, the end user’s search will be limited to a portion of the data managed in the index.

If several FilterGroups are defined and the logged-in user is entitled to these different configurations, they will be displayed as tabs in the final interface.

Note: a FilterGroup can be :

  • static (formula extensions): the filter is defined “in hard” in the XML configuration
  • dynamic: the filter is dynamic according to the execution context (connected user for example); in this case, the filter can be realized via SDK.
Note

If you filter according to a customtag, this one must not be present in the search criteria, otherwise the filtergroup does not work.

Example:

<filterGroups>
    <filterGroup default="true" name="caseBasicSearchGroup1" label="LG_caseBasicSearchGroup1">
        <filter name="Champlistemultiple" type="text" operator="contents" value="Ap" customValue="false" format="" normalized="false" />
    </filterGroup>
</filterGroups>

Source : https://wiki.myvdoc.net/xwiki/bin/view/Dev+Floor/BuildSearchWithFilterGroup

Resultgroup

The objective here is to present the search results in a personalized way by grouping them. The grouping can be done from an SDK extension class: we can therefore imagine grouping from any functional rule.

By default, there are 2 functional rules available:

  • Group by index (if our search is based on several indexes)
  • Group by CustomTag value:
    • Example: group by document status for Process document indexing.

Notes :

  • Warning, If a CustomTag is used to constitute a resultGroup, it cannot be used in the search form because the search result will necessarily contain all the values of this customTag.
  • ResultGroups can have parameters or not.

Extension classes

Index Grouping Extension Class:

  • com.axemble.axvdocsearch.extensions.implementation.IResultGroupsExtension.IndexesResultGroupsExtension
  • This class does not require any parameters.

Grouping extension class link to the value of a field :

  • com.axemble.axvdocsearch.extensions.implementation.IResultGroupsExtension.CustomTagResultGroupsExtension
  • Parameters : customTagKey (required): name of the CustomTag concerned customTagCollectionKey : boolean value to be set to “true” if the CustomTag is a “collection”.

Index Grouping Extension Class:

  • com.axemble.axvdocsearch.extensions.implementation.resultgroups.IndexesResultGroupsExtension
  • This class does not require any parameters.

Grouping extension class link to the value of a field :

  • com.axemble.axvdocsearch.extensions.implementation.resultgroups.CustomTagResultGroupsExtension
  • Parameters : customTagKey (required): name of the CustomTag concerned customTagCollectionKey : boolean value to be set to “true” if the CustomTag is a “collection”.

Example

<resultGroups extension="com.axemble.axvdocsearch.extensions.implementation.IResultGroupsExtension.CustomTagResultGroupsExtension" >
    <parameters>
        <parameter key="customTagKey" value="Champlistesimple" />
    </parameters>
</resultGroups>
<resultGroups extension="com.axemble.axvdocsearch.extensions.implementation.resultgroups.CustomTagResultGroupsExtension" >
    <parameters>
        <parameter key="customTagKey" value="Champlistesimple" />
    </parameters>
</resultGroups>

Source : https://wiki.myvdoc.net/xwiki/bin/view/Dev+Floor/BuildSearchWithResultGroup

Pagination

Standard paging mode : in memory

With this pagination mode, activated by default, Xtended Search retrieves the objects from a search result and asks Process to manage them in memory: pagination, sorting. If this mode is perfectly suitable for small volumes, it is not at all suitable for large quantities of data.

Indeed, if you have a search with 100,000 results and you display the first 10 results of the view, you have 100,000 objects that have been mounted in memory and that are managed by the Process view pagination system.

Setting this mode: internalPagination=“false” (in the XML attributes of the “view”).

Internal pagination mode: low level in the index

In this mode of pagination, it is the performance which is privileged for the large volumes.

Indeed, we move the actions of pagination and sorting to the level of the index and we only store in memory the data displayed on the screen at a given time.

If we take the example of the previous paragraph, I will have, with this mode of pagination, only 10 objects mounted in memory.

Setting of this mode: internalPagination=“true” (in the XML attributes of the “view”)

Advantages:

  • Searches are much faster to execute
  • We drastically reduce the memory load in Process which is problematic on large volumes.

Constraints (the pagination system is slightly lighter):

  • You cannot go directly to a given page: you cannot go directly to page 46 of my search results
  • You cannot go directly to the last page of my search results
  • You can’t display the number of search results: in fact, we don’t know it yet; even if we could have an estimate of the total number of results in the index, the search extension or security classes would be likely to distort the result.

Warning (important remark at SDK level): In a search extension, there is an onPrepareDocuments event that returns the totality of the search results before displaying them; in this mode, this event will not be called since, as we have explained, we have not loaded all the information. On the other hand, the onPrepareDocument event will of course be called as for the other pagination mode.

Example

<search name="SubWorkFlowInstanceTableSearch"
    label="LG_SubWorkFlowInstanceTableSearch" 
    sourceIndexes="SubWorkFlowInstanceTableIndex" 
    extension="" 
    securityExtension="com.vdoc.ExempleVDocSecurityExtension" 
    fullTextInput="true" 
    defaultViewRowsPerPage="10" 
    linkable="true" 
    autoExecuteSearch="true">
    
    <customtag name="ChText2" type="text" label="ChText2"/>
    <customtag name="nombre" type="number" label="nombre"/>

    
    <view linksTarget="_blank" toolTips="" showReference="true" showTitle="false"  internalPagination="false">
        <column name="ChText2" type="text"  label="ChText2" />
        <column name="nombre" type="number" label="nombre" />

    </view>
</search>

defaultViewRowsPerPage : integer, default 10. Default number of lines per page.

Source : https://wiki.myvdoc.net/xwiki/bin/view/Dev+Floor/AboutPaginationModes

Override the rendering of a result column

The base class is the following : com.axemble.axvdocsearch.extensions.base.implementation.ISearchExtension.BaseSearchExtension

The base class is the following : com.axemble.axvdocsearch.extensions.base.implementation.search.BaseSearchExtension

So we will inherit from this class to override one (or more) columns.

To do this, we will have to redefine the customizeViewColumnControl method. This method allows to override in the search results the graphical controls used to display the content of a column. So we can build the widget we want and return it to override the standard control.

Example:

import com.axemble.axvdocsearch.core.beans.Column;
import com.axemble.axvdocsearch.core.beans.Document;
import com.axemble.axvdocsearch.extensions.base.implementation.ISearchExtension.BaseSearchExtension;
import com.axemble.vdp.ui.framework.foundation.Widget;
import com.axemble.vdp.ui.framework.widgets.CtlButton;
import com.axemble.vdp.ui.framework.widgets.CtlText;

public class SearchExtension extends BaseSearchExtension {
	/** the default class logger */
	private static com.axemble.vdoc.sdk.utils.Logger log = com.axemble.vdoc.sdk.utils.Logger.getLogger(SearchExtension.class);

	@Override
	public Document prepareDocument(Document document) {
		return super.prepareDocument(document);
	}

	@Override
	public Widget customizeViewColumnControl(Document document, Column column, Object widget) {

		try {
			if ("ChText2".equals(column.getName())) {
				CtlButton button = new CtlButton(column.getName(), new CtlText(document.getMCustomValues().get(column.getName()).toString()));
				return button;
			}
		} catch (Exception e) {
			log.error(e);
		}
		return super.customizeViewColumnControl(document, column, widget);
	}
}
import com.axemble.axvdocsearch.core.beans.Column;
import com.axemble.axvdocsearch.core.beans.Document;
import com.axemble.axvdocsearch.extensions.base.implementation.search.BaseSearchExtension;
import com.axemble.vdp.ui.framework.foundation.Widget;
import com.axemble.vdp.ui.framework.widgets.CtlButton;
import com.axemble.vdp.ui.framework.widgets.CtlText;

public class SearchExtension extends BaseSearchExtension {
	/** the default class logger */
	private static com.axemble.vdoc.sdk.utils.Logger log = com.axemble.vdoc.sdk.utils.Logger.getLogger(SearchExtension.class);

	@Override
	public Document prepareDocument(Document document) {
		return super.prepareDocument(document);
	}

	@Override
	public Widget customizeViewColumnControl(Document document, Column column, Object widget) {

		try {
			if ("ChText2".equals(column.getName())) {
				CtlButton button = new CtlButton(column.getName(), new CtlText(document.getMCustomValues().get(column.getName()).toString()));
				return button;
			}
		} catch (Exception e) {
			log.error(e);
		}
		return super.customizeViewColumnControl(document, column, widget);
	}
}

Source : https://wiki.myvdoc.net/xwiki/bin/view/Dev+Floor/HowToOverloadSearchColumnRendering

Initialize the value of a search field

We will present here a simple example to pre-fill a search form via SDK.

To be able to read and write in the search form we need to extend IResourceSearchExtension.

This interface will provide you with an IRessource and an IResourceController which behaves like in other Process modules.

public class DemoResourceSearchExtension extends BaseSearchExtension implements IResourceSearchExtension {
    private IResource resource;
    private IResourceController resourceController;
    
    /* 
    * get serach form resource and controller
    */
    @Override
    public void initialize(Map<String, Object> parameters, IUser user, Search search, IResource resource, IResourceController resourceController) {
        this.initialize(parameters, user, search);
        this.resource = resource;
        this.resourceController = resourceController;
    }
    
    /* 
    * the value on field Champtexte
    */
    @Override
    public void onAfterLoad() {
        this.resource.setValue("Champtexte", "Hello world!");
    }
}

Source : https://wiki.myvdoc.net/xwiki/bin/view/Dev+Floor/HowToInitializeDefaultSearchFieldValue

Dynamic tooltips

The toolTips attribute of the search view allows you to fill in one or more fields that will be used as a “tooltip” when the user moves the mouse over the search result lines.

If several fields are to be filled in, they must be separated by “|”. The content will be truncated if it exceeds a certain number of characters.

Here is a possible XML configuration:

<search name="SubWorkFlowInstanceTableSearch"
    label="LG_SubWorkFlowInstanceTableSearch" 
    sourceIndexes="SubWorkFlowInstanceTableIndex" 
    extension="com.vdoc.SearchExtension" 
    securityExtension="com.vdoc.ExempleVDocSecurityExtension" 
    fullTextInput="true" 
    defaultViewRowsPerPage="10" 
    linkable="true" 
    autoExecuteSearch="true">
    
    <customtag name="ChText2" type="text" label="ChText2"/>
    <customtag name="nombre" type="number" label="nombre"/>
    
    <view linksTarget="_blank" toolTips="ChText2|nombre" showReference="true" showTitle="false"  internalPagination="false">
        <column name="ChText2" type="text"  label="ChText2" />
        <column name="nombre" type="number" label="nombre" />
    </view>
</search>

Source : https://wiki.myvdoc.net/xwiki/bin/view/Dev+Floor/HowToSetDynamicTooltips