Index: main/plugin-odf/i18n/messages_fr.xml
===================================================================
--- main/plugin-odf/i18n/messages_fr.xml	(revision 38871)
+++ main/plugin-odf/i18n/messages_fr.xml	(working copy)
@@ -945,6 +945,9 @@
 	<message key="PLUGINS_ODF_UITOOL_PROGRAM_ORGUNIT">Composante(s)</message>
 	<message key="PLUGINS_ODF_UITOOL_PROGRAM_LANG">Langue</message>
 	<message key="PLUGINS_ODF_UITOOL_PROGRAM_TITLE">Listes des Formations</message>	
+	<message key="PLUGINS_ODF_UITOOL_PROGRAM_CONTENTTYPE">Type de contenu</message>	
+	<message key="PLUGINS_ODF_UITOOL_PROGRAM_CONTENTTYPE_PROGRAM">Formation</message>	
+	<message key="PLUGINS_ODF_UITOOL_PROGRAM_CONTENTTYPE_SUBPROGRAM">Parcours</message>	
 
 	<!-- +
 		 | Action Add a new container
Index: main/plugin-odf/plugin.xml
===================================================================
--- main/plugin-odf/plugin.xml	(revision 38871)
+++ main/plugin-odf/plugin.xml	(working copy)
@@ -2594,6 +2594,192 @@
 					<file>js/org/ametys/odf/program/ProgramStructXmlLoader.js</file>
 				</scripts>
     		</extension>
+            
+            
+            <extension id="org.ametys.odf.program.ProgramSubProgramFactoryButton"
+                       point="org.ametys.cms.workspace.uitool.UIToolsFactoriesManager"
+                       class="org.ametys.cms.clientsideelement.SearchClientSideElement">
+                <action class="org.ametys.cms.tool.search.SearchToolFactory">
+                    <param name="role">uitool-odf-program-subprogram</param>
+                    <param name="title" i18n="true">PLUGINS_ODF_PROGRAM_LABEL</param>
+                    <param name="description" i18n="true">PLUGINS_ODF_PROGRAM_DESCRIPTION</param>
+                    <param name="footer" i18n="true">PLUGINS_ODF_PROGRAM_FOOTER</param>
+                    <param name="icon-small" file="true">img/education/search_program_16.png</param>
+                    <param name="icon-medium" file="true">img/education/search_program_32.png</param>
+                    <param name="icon-large" file="true">img/education/search_program_48.png</param>
+                    <param name="default-location"></param> 
+                </action> 
+                <search-url plugin="odf">program/search/program-subprogram-list.xml</search-url>   
+                <export-url plugin="odf">program/search/export.xls</export-url>     
+                <search-criteria>
+                    <criteria name="title" type="string" column="1">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_NAME</label>
+                        <test-operator>wd</test-operator>
+                    </criteria>
+                    <criteria name="ctype" type="string" column="1" metadata="false" mandatory="true">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_CONTENTTYPE</label>
+                        <test-operator>eq</test-operator>
+                        <enumeration>
+                            <entry>
+    		            		<label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_CONTENTTYPE_PROGRAM</label>
+    		            		<value>program</value>
+    		            	</entry>
+    		            	<entry>
+    		            		<label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_CONTENTTYPE_SUBPROGRAM</label>
+    		            		<value>subprogram</value>
+    		            	</entry>
+                        </enumeration>
+                    </criteria>
+                    <criteria name="catalog" type="string" column="1">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_CATALOG</label>
+                        <test-operator>eq</test-operator>
+                        <enumeration>
+                            <custom-enumerator class="org.ametys.odf.catalog.CatalogEnumerator">
+                                <all-option>blank</all-option>
+                            </custom-enumerator>
+                        </enumeration>
+                        <widget>sorted-enumeration</widget>
+                    </criteria>
+                    <criteria name="workflow-step" type="string" column="1" metadata="false">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_WORKFLOW_STEP</label>
+                        <test-operator>eq</test-operator>
+                        <enumeration>
+                            <custom-enumerator class="org.ametys.cms.workflow.DefaultWorkflowStepEnumerator">
+                                <workflow-name>program</workflow-name>
+                                <exclude-workflow-steps>
+                                    <id>0</id>
+                                    <id>9999</id>
+                                </exclude-workflow-steps>
+                            </custom-enumerator>
+                        </enumeration>
+                    </criteria>
+                    <criteria name="cdmCode" type="string" column="1">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_CDM_CODE</label>
+                        <test-operator>wd</test-operator>
+                    </criteria>
+                    <criteria name="orgUnit" type="string" column="2">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_ORGUNIT</label>
+                        <test-operator>eq</test-operator>
+                        <widget>orgunit</widget>
+                        <enumeration>
+                            <custom-enumerator class="org.ametys.odf.orgunit.OrgUnitEnumerator">
+                                <all-option>blank</all-option>
+                            </custom-enumerator>
+                        </enumeration>
+                    </criteria>
+                    <criteria name="code" type="string" column="2">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_DIPCODE</label>
+                        <test-operator>wd</test-operator>
+                    </criteria>
+                    <criteria name="degree" type="string" column="2">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_DEGREE</label>
+                        <test-operator>eq</test-operator>
+                        <widget>sorted-enumeration</widget>
+                        <enumeration>
+                            <custom-enumerator class="org.ametys.odf.enumeration.StaticODFEnumerator">
+                                <all-option>blank</all-option>
+                                <constant>DEGREE</constant>
+                            </custom-enumerator>
+                        </enumeration>
+                    </criteria>
+                    <criteria name="place" type="string" column="2">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_PLACE</label>
+                        <test-operator>eq</test-operator>
+                        <enumeration>
+                            <custom-enumerator class="org.ametys.odf.enumeration.StaticODFEnumerator">
+                                <all-option>blank</all-option>
+                                <constant>PLACE</constant>
+                            </custom-enumerator>
+                        </enumeration>
+                    </criteria>
+                    <criteria name="lastModified" type="date" column="3">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_LASTMODIFIED_AFTER</label>
+                        <test-operator>ge</test-operator>
+                    </criteria>
+                    <criteria name="lastModified" type="date" column="3">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_LASTMODIFIED_BEFORE</label>
+                        <test-operator>le</test-operator>
+                    </criteria>
+                    <criteria name="contributor" type="string" column="3">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_AUTHOR</label>
+                        <test-operator>wd</test-operator>
+                    </criteria>
+                </search-criteria>  
+                <property-mapping>
+                    <property id="id" path="@id"/>
+                    <property id="language" path="@language"/>
+                    <property id="language-image" path="@language-image"/>
+                    <property id="title" path="metadata/title"/>
+                    <property id="cdmCode" path="metadata/cdmCode"/>
+                    <property id="orgUnit" path="metadata/orgUnit"/>
+                    <property id="code" path="metadata/code"/>
+                    <property id="catalog" path="metadata/catalog"/>
+                    <property id="contributor" path="metadata/contributor"/>
+                    <property id="icon-small" path="@smallIcon"/>
+                    <property id="icon-medium" path="@mediumIcon"/>
+                    <property id="content-type" path="content-type"/>
+                    <property id="lastModified" path="metadata/lastModified" type="date"/>
+                    <property id="workflow-step" path="workflow-step"/>
+                    <property id="workflow-icon-small" path="workflow-icon-small"/>
+                    <property id="workflow-icon-medium" path="workflow-icon-medium"/>
+                </property-mapping>
+                <columns>
+                    <column id="title" hideable="false">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_NAME</label>
+                        <width>270</width>
+                        <renderer>org.ametys.cms.tool.search.SearchTool.renderTitle</renderer>
+                    </column>
+                    <column id="language">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_LANG</label>
+                        <width>30</width>
+                        <renderer>org.ametys.odf.program.ProgramTools.renderLanguage</renderer>
+                    </column>
+                    <column id="code">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_DIPCODE</label>
+                        <width>100</width>
+                    </column>
+                    <column id="catalog">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_CATALOG</label>
+                        <width>150</width>
+                    </column>
+                    <column id="cdmCode">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_CDM_CODE</label>
+                        <width>100</width>
+                    </column>
+                    <column id="orgUnit">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_PROGRAM_ORGUNIT</label>
+                        <width>150</width>
+                        <renderer>org.ametys.odf.program.ProgramTools.renderMultipleMetadata</renderer>
+                    </column>
+                    <column id="contributor">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_AUTHOR</label>
+                        <width>150</width>
+                    </column>
+                    <column id="lastModified">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_LASTMODIFIED</label>
+                        <width>130</width>
+                        <renderer>org.ametys.cms.tool.search.SearchTool.renderDateTime</renderer>
+                    </column>
+                    <column id="workflow-step">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_WORKFLOW_STEP</label>
+                        <width>50</width>
+                        <renderer>org.ametys.cms.tool.search.SearchTool.renderWorlflowStep</renderer>
+                    </column>
+                    <column id="content-type" hidden="true">
+                        <label i18n="true">PLUGINS_ODF_UITOOL_SEARCH_CONTENT_CONTENTTYPE</label>
+                        <width>150</width>
+                    </column>
+                </columns>
+                <nb-result-per-page>50</nb-result-per-page>                
+                <scripts>
+                    <file plugin="cms">js/org/ametys/cms/helper/SearchContentHMIHelper.i18n.js</file>
+                    <file plugin="cms">js/org/ametys/cms/tool/search/SearchTool.i18n.js</file>
+                    <file plugin="cms">js/org/ametys/cms/tool/search/SearchToolFactory.js</file>
+                </scripts>
+                <css>
+                    <file plugin="cms">css/search.css</file>
+                </css>
+            </extension>
         </extensions>
     </feature>
    
Index: main/plugin-odf/sitemap.xmap
===================================================================
--- main/plugin-odf/sitemap.xmap	(revision 38871)
+++ main/plugin-odf/sitemap.xmap	(working copy)
@@ -31,6 +31,7 @@
 			<map:generator name="path-to-id" src="org.ametys.odf.orgunit.generators.ConvertOrgUnitPathToId"/>
 			
 			<map:generator name="program-search" src="org.ametys.odf.program.generators.ProgramSearchGenerator" />
+			<map:generator name="program-subprogram-search" src="org.ametys.odf.program.generators.ProgramSubProgramSearchGenerator" />
 			<map:generator name="program-tree" src="org.ametys.odf.program.generators.ProgramStructureGenerator"/>
 			
 			<map:generator name="course-search" src="org.ametys.odf.course.generators.SearchCoursesGenerator" />
@@ -618,6 +619,15 @@
 				<map:serialize type="xml" />
 			</map:match>
 			
+			<map:match pattern="program/search/program-subprogram-list.xml">
+				<map:generate type="program-subprogram-search" />
+				<map:transform type="i18n">
+					<map:parameter name="locale" value="{locale:locale}"/>
+	            	<map:parameter name="plugin" value="{request-attr:pluginName}"/>
+				</map:transform>
+				<map:serialize type="xml" />
+			</map:match>
+			
 			<map:match pattern="program/search/export.xls">
                 <map:act type="set-header"> 
                     <map:parameter name="Content-Disposition" value="attachment"/>
Index: main/plugin-odf/src/org/ametys/odf/program/generators/ProgramSubProgramSearchGenerator.java
===================================================================
--- main/plugin-odf/src/org/ametys/odf/program/generators/ProgramSubProgramSearchGenerator.java	(revision 0)
+++ main/plugin-odf/src/org/ametys/odf/program/generators/ProgramSubProgramSearchGenerator.java	(revision 0)
@@ -0,0 +1,57 @@
+/*
+ *  Copyright 2016 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.odf.program.generators;
+
+import org.apache.cocoon.environment.Request;
+
+import org.ametys.cms.repository.ContentTypeExpression;
+import org.ametys.odf.program.Program;
+import org.ametys.odf.program.ProgramFactory;
+import org.ametys.odf.program.SubProgram;
+import org.ametys.odf.program.SubProgramFactory;
+import org.ametys.plugins.repository.query.SortCriteria;
+import org.ametys.plugins.repository.query.expression.Expression;
+import org.ametys.plugins.repository.query.expression.Expression.Operator;
+
+/**
+ * Search the {@link Program}s and {@link SubProgram}s matching criteria passed in request parameters
+ */
+public class ProgramSubProgramSearchGenerator extends ProgramSearchGenerator
+{
+    @Override
+    protected String getXPathQuery(Request request)
+    {
+        Expression expr = createExpression(request);
+        SortCriteria sortCriteria = getSortCriteria(request);
+
+        String ctype = "subprogram".equals(request.getParameter("string-eq-ctype")) ? SubProgramFactory.SUBPROGRAM_NODETYPE : ProgramFactory.PROGRAM_NODETYPE;
+        
+        return org.ametys.plugins.repository.query.QueryHelper.getXPathQuery(null, ctype, expr, sortCriteria);
+    }
+    
+    @Override
+    protected Expression createContentTypeExpressions(Request request)
+    {
+        if ("subprogram".equals(request.getParameter("string-eq-ctype")))
+        {
+            return new ContentTypeExpression(Operator.EQ, SubProgramFactory.SUBPROGRAM_CONTENT_TYPE);
+        }
+        else
+        {
+            return new ContentTypeExpression(Operator.EQ, ProgramFactory.PROGRAM_CONTENT_TYPE);
+        }
+    }
+}
