Index: main/plugin-cms/resources/js/org/ametys/cms/widgets/SelectTypedMetadata.i18n.js
===================================================================
--- main/plugin-cms/resources/js/org/ametys/cms/widgets/SelectTypedMetadata.i18n.js	(revision 0)
+++ main/plugin-cms/resources/js/org/ametys/cms/widgets/SelectTypedMetadata.i18n.js	(revision 0)
@@ -0,0 +1,142 @@
+/*
+ *  Copyright 2014 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.
+ */
+
+Ext.namespace('org.ametys.cms.widgets');
+
+//Register widget
+org.ametys.utils.Widgets.registerWidget ('string', 'typed-metadata', 'org.ametys.cms.widgets.SelectTypedMetadata');
+
+org.ametys.cms.widgets.SelectTypedMetadata = function(config, enumeratedValues) 
+{
+	this.store = new Ext.data.SimpleStore({
+		idIndex: 0,
+        fields: [
+           {name: 'value'},
+           {name: 'label'}        
+        ]
+	});
+	
+	this._metadataSetName = config.metadataSetName;
+	this._metadataType = config.metadataType;
+	
+	org.ametys.cms.widgets.SelectTypedMetadata.superclass.constructor.call(this, config, enumeratedValues);
+};
+
+Ext.extend(org.ametys.cms.widgets.SelectTypedMetadata, org.ametys.form.ComboField, {
+	height: 107,
+	width: 100,
+	minChars: 0,
+	triggerAction: 'all',
+	forceSelection: true,
+	selectOnFocus: true,
+	valueField: 'value',
+	displayField: 'label',
+	mode: 'local'
+});
+
+/**
+ * Force expand on focus
+ */
+org.ametys.cms.widgets.SelectTypedMetadata.prototype._onFocus = function ()
+{
+	if(this.triggerAction == 'all') 
+	{
+        this.doQuery(this.allQuery, true);
+    } 
+	else 
+	{
+        this.doQuery(this.getRawValue());
+    }
+}
+
+org.ametys.cms.widgets.SelectTypedMetadata.prototype.onSelectContentTypes = function (cTypes)
+{
+	this._cTypes = cTypes;
+	this._loadSkins();
+}
+
+org.ametys.cms.widgets.SelectTypedMetadata.prototype.onRender = function(ct, position)
+{
+	org.ametys.cms.widgets.SelectTypedMetadata.superclass.onRender.call(this, ct, position);
+	this._loadSkins();
+
+	this.addListener('focus', this._onFocus, this);
+	
+	org.ametys.cms.widgets.ContentTypesWidget.registerListener (this);
+}
+
+org.ametys.cms.widgets.SelectTypedMetadata.prototype._loadSkins = function ()
+{
+	params = {};
+	params.ids = this._cTypes;
+	params.metadataSetName = this._metadataSetName;
+	params.metadataType = this._metadataType;
+
+	console.log(this._metadataSetName+"----"+this._metadataType);
+
+	
+	var firstLoad = false;
+	if (typeof this._cTypes == 'undefined')
+	{
+		firstLoad = true;
+	}
+	
+	var serverMessage = new org.ametys.servercomm.ServerMessage('cms', '/common-typed-metadata', params, org.ametys.servercomm.ServerComm.PRIORITY_MAJOR, this._loadSkinsCb, this, [firstLoad]);
+	org.ametys.servercomm.ServerComm.getInstance().send(serverMessage);
+}
+
+org.ametys.cms.widgets.SelectTypedMetadata.prototype._loadSkinsCb = function (response, args)
+{
+	if (org.ametys.servercomm.ServerComm.handleBadResponse("<i18n:text i18n:key="WIDGET_SELECTTYPEDMETADATA_FILTER_LOAD_ERROR"/>", response, "org.ametys.web.administration.SkinsWidget"))
+	{
+		return;
+	}
+	
+	var store = this.getStore();
+	store.removeAll();	
+	
+	var metadataTab = [];
+	
+	var metadatas = response.selectNodes("metadata/metadata");
+	
+	var noData = {
+            value: "",
+            label: "<i18n:text i18n:key="WIDGET_SELECTTYPEDMETADATA_FILTER_NONE"/>"
+    };
+	metadataTab.push(new this.store.recordType(noData));
+
+	for (var i=0; i &lt; metadatas.length; i++)
+	{
+		var data = {
+	            value: metadatas[i].getAttribute('name'),
+	            label: metadatas[i].selectSingleNode('label')[org.ametys.servercomm.ServerComm.xmlTextContent]
+	    };
+
+		metadataTab.push(new this.store.recordType(data));
+	}
+	
+	this.store.add(metadataTab);
+	
+	// We set the value after the loading of the store
+	this.setValue(this.getValue());
+	
+	// Check if it's the first time we load (cType is not defined before first load)
+	var firstLoad = args[0];
+	if (!firstLoad &amp;&amp; this.store.find('value',this.getValue()) == -1 )
+	{
+		this.setValue("");
+	}
+}
\ No newline at end of file
Index: main/plugin-cms/src/org/ametys/cms/contenttype/CommonTypedMetadataGenerator.java
===================================================================
--- main/plugin-cms/src/org/ametys/cms/contenttype/CommonTypedMetadataGenerator.java	(revision 0)
+++ main/plugin-cms/src/org/ametys/cms/contenttype/CommonTypedMetadataGenerator.java	(revision 0)
@@ -0,0 +1,229 @@
+/*
+ *  Copyright 2010 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.cms.contenttype;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.generation.ServiceableGenerator;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.xml.sax.SAXException;
+
+import org.ametys.cms.form.RepeaterField;
+import org.ametys.cms.lucene.FieldNames;
+import org.ametys.runtime.util.I18nizableText;
+
+/**
+ * SAX common metadata given content types and metadata-set
+ */
+public class CommonTypedMetadataGenerator extends ServiceableGenerator
+{
+    /** The content type extension point */
+    protected ContentTypeExtensionPoint _contentTypeEP;
+    
+    @Override
+    public void service(ServiceManager smanager) throws ServiceException
+    {
+        super.service(smanager);
+        _contentTypeEP = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE);
+    }
+    
+    @Override
+    public void generate() throws IOException, SAXException, ProcessingException
+    {
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        
+        String contentTypesIdsAsString = request.getParameter("ids");
+        String metadataSetName = request.getParameter("metadataSetName");
+        String authorizedMetadataTypesAsString = request.getParameter("metadataType");
+        
+        String[] authorizedMetadataTypes = StringUtils.split(authorizedMetadataTypesAsString);
+
+        boolean hasDocument = false;
+        
+        String[] contentTypeIds = null;
+        if (!StringUtils.isEmpty(contentTypesIdsAsString))
+        {
+            contentTypeIds = contentTypesIdsAsString.split(",");
+        }
+        else
+        {
+            contentTypeIds =  getAllAvailablesContentTypes(request, true);
+            hasDocument = true;
+        }
+        
+        Map<String, MetadataDefinition> commonMetadata = null;
+        
+        if (StringUtils.isNotEmpty(metadataSetName))
+        {
+            for (String contentTypeId : contentTypeIds)
+            {
+                ContentType contentType = _contentTypeEP.getExtension(contentTypeId);
+                
+                // Documents are not a content-type
+                if (!contentTypeId.equals("resource"))
+                {
+                    MetadataSet metadataSet = contentType.getMetadataSetForView(metadataSetName);
+                    
+                    // Test if the metadataSetName view is defined
+                    if (metadataSet != null)
+                    {
+                        Map<String, MetadataDefinition> authorizedMetadata = new HashMap<String, MetadataDefinition>();
+                        _getTypedMetadata(contentType, metadataSet, authorizedMetadataTypes, authorizedMetadata);
+                        
+                        if (commonMetadata == null)
+                        {
+                            commonMetadata = authorizedMetadata;
+                        }
+                        else
+                        {
+                            // Maps intersection
+                            commonMetadata.keySet().retainAll(authorizedMetadata.keySet());
+                        }
+                    }
+                }
+                else
+                {
+                    hasDocument = true;
+                }
+            }
+        }
+        
+        saxCommonMetadata (commonMetadata, hasDocument);
+    }
+
+    private void _getTypedMetadata(MetadataDefinitionHolder metadataDefHolder, MetadataSetElement metadataSetElement, String[] authorizedMetadataTypes, Map<String, MetadataDefinition> authorizedMetadata)
+    {
+        for (MetadataSetElement subMetadataSetElement : metadataSetElement.getElements())
+        {
+            if (subMetadataSetElement instanceof MetadataDefinitionReference)
+            {
+                String metadataName = ((MetadataDefinitionReference) subMetadataSetElement).getMetadataName();
+               
+                MetadataDefinition metaDef = metadataDefHolder.getMetadataDefinition(metadataName);
+                String metadataId = metaDef.getId();
+                
+                if (ArrayUtils.contains(authorizedMetadataTypes, metaDef.getType().toString()))
+                {
+                    if (metadataId.startsWith("/")) // FIXME cf Patch Bad Indexation Repeater (missing '/')
+                    {
+                        metadataId = StringUtils.substring(metadataId, 1); 
+                    }
+                    authorizedMetadata.put(metadataId, metaDef);
+                }
+               
+                if (metaDef.getType() == MetadataType.COMPOSITE)
+                {
+                    if (metaDef instanceof DefaultContentType.RestrictedRepeaterDefinition)
+                    {
+                        //FIXME cf Patch Indexation lucene Repeater
+                    }
+                    else
+                    {
+                        _getTypedMetadata(metaDef, subMetadataSetElement, authorizedMetadataTypes, authorizedMetadata);
+                    }
+                }
+            }
+            else if (subMetadataSetElement instanceof Fieldset)
+            {
+                _getTypedMetadata(metadataDefHolder, subMetadataSetElement, authorizedMetadataTypes, authorizedMetadata);
+            }
+        }
+    }
+    
+    /**
+     * SAX the common metadata
+     * @param commonMetadata the name of metadata to SAX
+     * @param hasDocument true if there is documents in between
+     * @throws SAXException if an error occurred while saxing
+     */
+    protected void saxCommonMetadata (Map<String, MetadataDefinition> commonMetadata, boolean hasDocument) throws SAXException
+    {
+        contentHandler.startDocument();
+        XMLUtils.startElement(contentHandler, "metadata");
+        
+        // If "Document" is not selected in the list
+        if (!hasDocument)
+        {
+            if (commonMetadata != null)
+            {
+                for (String name : commonMetadata.keySet())
+                {
+                    AttributesImpl attrs = new AttributesImpl();
+                    attrs.addCDATAAttribute("name", name);
+                    
+                    MetadataType metadataType = commonMetadata.get(name).getType();
+                    attrs.addCDATAAttribute("type", metadataType.toString());
+                    
+                    XMLUtils.startElement(contentHandler, "metadata", attrs);
+                    commonMetadata.get(name).getLabel().toSAX(contentHandler, "label");
+                    XMLUtils.endElement(contentHandler, "metadata");
+                }
+            }
+            
+            // Always add "Last validation"
+            AttributesImpl attrs = new AttributesImpl();
+            attrs.addAttribute("", "name", "name", "CDATA", FieldNames.LAST_VALIDATION);
+            attrs.addAttribute("", "type", "type", "CDATA", MetadataType.DATE.toString());
+            XMLUtils.startElement(contentHandler, "metadata", attrs);
+            new I18nizableText("plugin.web", "PLUGINS_WEB_LAST_VALIDATION_DATE").toSAX(contentHandler, "label");
+            XMLUtils.endElement(contentHandler, "metadata");
+        }
+
+        // Always add "Last modified"
+        AttributesImpl attrs = new AttributesImpl();
+        attrs.addAttribute("", "name", "name", "CDATA", FieldNames.LAST_MODIFIED);
+        attrs.addAttribute("", "type", "type", "CDATA", MetadataType.DATE.toString());
+        XMLUtils.startElement(contentHandler, "metadata", attrs);
+        new I18nizableText("plugin.web", "PLUGINS_WEB_LAST_MODIFICATION_DATE").toSAX(contentHandler, "label");
+        XMLUtils.endElement(contentHandler, "metadata");
+        
+        XMLUtils.endElement(contentHandler, "metadata");
+        contentHandler.endDocument();
+    }
+    
+    /**
+     * Get all the available content types 
+     * @param request the request
+     * @param publicOnly Only the non private content types will be returned
+     * @return all the available content types 
+     */
+    protected String[] getAllAvailablesContentTypes (Request request, boolean publicOnly)
+    {
+        Set<String> publicTypes = new HashSet<String>();
+        
+        for (String id : _contentTypeEP.getExtensionsIds())
+        {
+            if (!publicOnly || !_contentTypeEP.getExtension(id).isPrivate())
+            {
+                publicTypes.add(id);
+            }
+        }
+        
+        return publicTypes.toArray(new String[publicTypes.size()]);
+    }
+}
\ No newline at end of file
