From 5a504fce07b9f6ac95364a5ea8315757f596b7b1 Mon Sep 17 00:00:00 2001 From: Mark Rogers Date: Sat, 20 Sep 2014 10:24:57 +0000 Subject: [PATCH] Merged HEAD-BUG-FIX (5.0/Cloud) to HEAD (5.0/Cloud) 85028: Merged PLATFORM1 (5.0/Cloud) to HEAD-BUG-FIX (5.0/Cloud) 84196: Addition of what I'm calling 'synthetic' facetable properties to SolrFacetService and REST API as part of ACE-2639. A synthetic property is something that is technically *NOT* a property, but which can be treated as such for the purposes of SOLR facetting/filtering. Currently we only support two synthetic properties: size and mimetype, which are defined within any Alfresco property of type d:content. This includes, but is not limited to, the cm:content property in all cm:content types in Alfresco. (Be careful with your cm:content. That name is heavily overloaded.) This checkin only supports what we need for 5.0. It is expressly not designed for resuse/extension in a general way. However, I have tried to push the less stable parts of this work into the implementation of the service and REST API and limit what's in the service interface to the more stable parts of the work. Also note that I had to add some l10n/i18n key-values for these synthetic properties. I've called the mimetype 'MIME type' in the l10n'd text as I have translations for that in all languages. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@85343 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../messages/content-model.properties | 4 ++ .../messages/content-model_de.properties | 4 ++ .../messages/content-model_es.properties | 4 ++ .../messages/content-model_fr.properties | 4 ++ .../messages/content-model_it.properties | 4 ++ .../messages/content-model_ja.properties | 4 ++ .../messages/content-model_nb.properties | 4 ++ .../messages/content-model_nl.properties | 4 ++ .../messages/content-model_pt_BR.properties | 4 ++ .../messages/content-model_ru.properties | 4 ++ .../messages/content-model_zh_CN.properties | 4 ++ .../impl/solr/facet/SolrFacetService.java | 36 ++++++++++- .../impl/solr/facet/SolrFacetServiceImpl.java | 60 +++++++++++++++++-- 13 files changed, 132 insertions(+), 8 deletions(-) diff --git a/config/alfresco/messages/content-model.properties b/config/alfresco/messages/content-model.properties index 35acc61fe5..dcda73a20a 100644 --- a/config/alfresco/messages/content-model.properties +++ b/config/alfresco/messages/content-model.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=Base Content Object cm_contentmodel.property.cm_content.title=Content cm_contentmodel.property.cm_content.description=Content +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=Size +cm_contentmodel.property.cm_content.cm_content.mimetype=MIME type + cm_contentmodel.type.cm_linkfile.title=File Link cm_contentmodel.type.cm_linkfile.description=Link to another File cm_contentmodel.property.cm_path.title=Link File Path diff --git a/config/alfresco/messages/content-model_de.properties b/config/alfresco/messages/content-model_de.properties index abfe188e0e..b1548a6850 100755 --- a/config/alfresco/messages/content-model_de.properties +++ b/config/alfresco/messages/content-model_de.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=Basis-Inhalts-Objekt cm_contentmodel.property.cm_content.title=Inhalt cm_contentmodel.property.cm_content.description=Inhalt +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=Gr\u00f6\u00dfe +cm_contentmodel.property.cm_content.cm_content.mimetype=MimeType + cm_contentmodel.type.cm_linkfile.title=Dateilink cm_contentmodel.type.cm_linkfile.description=Link zu einer anderen Datei cm_contentmodel.property.cm_path.title=Link Dateipfad diff --git a/config/alfresco/messages/content-model_es.properties b/config/alfresco/messages/content-model_es.properties index 7487652d1e..fc0310fd76 100755 --- a/config/alfresco/messages/content-model_es.properties +++ b/config/alfresco/messages/content-model_es.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=Objeto b\u00e1sico de contenido cm_contentmodel.property.cm_content.title=Contenido cm_contentmodel.property.cm_content.description=Contenido +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=Tama\u00f1o +cm_contentmodel.property.cm_content.cm_content.mimetype=Tipo MIME + cm_contentmodel.type.cm_linkfile.title=Enlace de fichero cm_contentmodel.type.cm_linkfile.description=Enlace a otro fichero cm_contentmodel.property.cm_path.title=Ruta de enlace de fichero diff --git a/config/alfresco/messages/content-model_fr.properties b/config/alfresco/messages/content-model_fr.properties index 9161a91461..acc5e91b1b 100755 --- a/config/alfresco/messages/content-model_fr.properties +++ b/config/alfresco/messages/content-model_fr.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=Objet de contenu de base cm_contentmodel.property.cm_content.title=Contenu cm_contentmodel.property.cm_content.description=Contenu +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=Taille +cm_contentmodel.property.cm_content.cm_content.mimetype=Type MIME + cm_contentmodel.type.cm_linkfile.title=Lien vers un fichier cm_contentmodel.type.cm_linkfile.description=Lien vers un autre fichier cm_contentmodel.property.cm_path.title=Chemin du lien vers le fichier diff --git a/config/alfresco/messages/content-model_it.properties b/config/alfresco/messages/content-model_it.properties index c327b88e16..fe33cb3046 100755 --- a/config/alfresco/messages/content-model_it.properties +++ b/config/alfresco/messages/content-model_it.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=Oggetto contenuto di base cm_contentmodel.property.cm_content.title=Contenuto cm_contentmodel.property.cm_content.description=Contenuto +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=Dimensioni +cm_contentmodel.property.cm_content.cm_content.mimetype=Tipo MIME + cm_contentmodel.type.cm_linkfile.title=Link a file cm_contentmodel.type.cm_linkfile.description=Link a un altro file cm_contentmodel.property.cm_path.title=Percorso file collegato diff --git a/config/alfresco/messages/content-model_ja.properties b/config/alfresco/messages/content-model_ja.properties index 850910c243..81ae5650fe 100755 --- a/config/alfresco/messages/content-model_ja.properties +++ b/config/alfresco/messages/content-model_ja.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=\u30b3\u30f3\u30c6\u30f3\u30c4\u306e cm_contentmodel.property.cm_content.title=\u30b3\u30f3\u30c6\u30f3\u30c4 cm_contentmodel.property.cm_content.description=\u30b3\u30f3\u30c6\u30f3\u30c4 +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=\u30b5\u30a4\u30ba +cm_contentmodel.property.cm_content.cm_content.mimetype=MIME\u30bf\u30a4\u30d7 + cm_contentmodel.type.cm_linkfile.title=\u30d5\u30a1\u30a4\u30eb\u30ea\u30f3\u30af cm_contentmodel.type.cm_linkfile.description=\u4ed6\u306e\u30d5\u30a1\u30a4\u30eb\u3078\u306e\u30ea\u30f3\u30af cm_contentmodel.property.cm_path.title=\u30ea\u30f3\u30af\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9 diff --git a/config/alfresco/messages/content-model_nb.properties b/config/alfresco/messages/content-model_nb.properties index f04aa48211..dde7ee5848 100755 --- a/config/alfresco/messages/content-model_nb.properties +++ b/config/alfresco/messages/content-model_nb.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=Grunninnholdobjekt cm_contentmodel.property.cm_content.title=Innhold cm_contentmodel.property.cm_content.description=Innhold +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=St\u00f8rrelse +cm_contentmodel.property.cm_content.cm_content.mimetype=Mimetype + cm_contentmodel.type.cm_linkfile.title=Filkobling cm_contentmodel.type.cm_linkfile.description=Kobling til annen fil cm_contentmodel.property.cm_path.title=Bane for koblingsfil diff --git a/config/alfresco/messages/content-model_nl.properties b/config/alfresco/messages/content-model_nl.properties index 4d1555bba1..6bee1ee530 100755 --- a/config/alfresco/messages/content-model_nl.properties +++ b/config/alfresco/messages/content-model_nl.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=Basiscontentobject cm_contentmodel.property.cm_content.title=Content cm_contentmodel.property.cm_content.description=Content +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=Grootte +cm_contentmodel.property.cm_content.cm_content.mimetype=Mimetype + cm_contentmodel.type.cm_linkfile.title=Bestandskoppeling cm_contentmodel.type.cm_linkfile.description=Koppeling naar een ander bestand cm_contentmodel.property.cm_path.title=Pad van bestandskoppeling diff --git a/config/alfresco/messages/content-model_pt_BR.properties b/config/alfresco/messages/content-model_pt_BR.properties index 45c236a948..5c4a98d578 100644 --- a/config/alfresco/messages/content-model_pt_BR.properties +++ b/config/alfresco/messages/content-model_pt_BR.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=Objeto de conte\u00fado base cm_contentmodel.property.cm_content.title=Conte\u00fado cm_contentmodel.property.cm_content.description=Conte\u00fado +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=Tamanho +cm_contentmodel.property.cm_content.cm_content.mimetype=Tipo mime + cm_contentmodel.type.cm_linkfile.title=Link do arquivo cm_contentmodel.type.cm_linkfile.description=Link para outro arquivo cm_contentmodel.property.cm_path.title=Caminho do link do arquivo diff --git a/config/alfresco/messages/content-model_ru.properties b/config/alfresco/messages/content-model_ru.properties index 2398c6c7ab..299e94dcb1 100755 --- a/config/alfresco/messages/content-model_ru.properties +++ b/config/alfresco/messages/content-model_ru.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=\u041E\u0441\u043D\u043E\u0432\u043D cm_contentmodel.property.cm_content.title=\u0421\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u043E\u0435 cm_contentmodel.property.cm_content.description=\u0421\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u043E\u0435 +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=\u0420\u0430\u0437\u043C\u0435\u0440 +cm_contentmodel.property.cm_content.cm_content.mimetype=\u0422\u0438\u043F MIME + cm_contentmodel.type.cm_linkfile.title=\u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 \u0444\u0430\u0439\u043B cm_contentmodel.type.cm_linkfile.description=\u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 \u0434\u0440\u0443\u0433\u043E\u0439 \u0444\u0430\u0439\u043B cm_contentmodel.property.cm_path.title=\u041F\u0443\u0442\u044C \u043A \u0441\u0432\u044F\u0437\u0430\u043D\u043D\u043E\u043C\u0443 \u0444\u0430\u0439\u043B\u0443 diff --git a/config/alfresco/messages/content-model_zh_CN.properties b/config/alfresco/messages/content-model_zh_CN.properties index 15a65c99a8..54d8eed51c 100755 --- a/config/alfresco/messages/content-model_zh_CN.properties +++ b/config/alfresco/messages/content-model_zh_CN.properties @@ -19,6 +19,10 @@ cm_contentmodel.type.cm_content.description=\u57fa\u5185\u5bb9\u5bf9\u8c61 cm_contentmodel.property.cm_content.title=\u5185\u5bb9 cm_contentmodel.property.cm_content.description=\u5185\u5bb9 +# Display labels for elements within the cm:content property type. +cm_contentmodel.property.cm_content.cm_content.size=\u5927\u5C0F +cm_contentmodel.property.cm_content.cm_content.mimetype=MIME \u7C7B\u578B + cm_contentmodel.type.cm_linkfile.title=\u6587\u4ef6\u94fe\u63a5 cm_contentmodel.type.cm_linkfile.description=\u94fe\u63a5\u5230\u53e6\u4e00\u4e2a\u6587\u4ef6 cm_contentmodel.property.cm_path.title=\u94fe\u63a5\u6587\u4ef6\u8def\u5f84 diff --git a/source/java/org/alfresco/repo/search/impl/solr/facet/SolrFacetService.java b/source/java/org/alfresco/repo/search/impl/solr/facet/SolrFacetService.java index d467e4d776..f38f6f81c2 100644 --- a/source/java/org/alfresco/repo/search/impl/solr/facet/SolrFacetService.java +++ b/source/java/org/alfresco/repo/search/impl/solr/facet/SolrFacetService.java @@ -38,7 +38,6 @@ import org.alfresco.service.namespace.QName; */ public interface SolrFacetService { - /** * Gets all the available facets. * @@ -117,9 +116,42 @@ public interface SolrFacetService * This method offers a convenient access point for getting all Facetable * content properties defined on the specified content class (type or aspect) or any of its inherited properties. * @param contentClass the QName of an aspect or type, whose facetable properties are sought. - * @param includeInheritedProperties {@code true} to include properties defined on supertypes. * @return a collection of facetable {@link PropertyDefinition}s. * @see Facetable */ public List getFacetableProperties(QName contentClass); + + /** + * This method gets all synthetic, facetable properties across all content models in the repository. + */ + public List getFacetableSyntheticProperties(); + + /** + * This method gets all synthetic, facetable properties defined on the specified content class (type or aspect) or any of its inherited properties. + * @param contentClass the QName of an aspect or type, whose synthetic, facetable properties are sought. + */ + public List getFacetableSyntheticProperties(QName contentClass); + + /** + * This class represents a special case of a property, examples being file size and MIME type, which + * are not modelled as Alfresco content model properties, but are instead stored as components + * within properties of type {@code cm:content}. + */ + public class SyntheticPropertyDefinition + { + public final PropertyDefinition containingPropertyDef; + public final String syntheticPropertyName; + public final QName dataTypeDefinition; + + public SyntheticPropertyDefinition(PropertyDefinition containingPropertyDef, String syntheticPropertyName, + QName syntheticDataTypeDefinition) + { + this.containingPropertyDef = containingPropertyDef; + this.syntheticPropertyName = syntheticPropertyName; + this.dataTypeDefinition = syntheticDataTypeDefinition; + } + + @Override public String toString() { return SyntheticPropertyDefinition.class.getSimpleName() + + "[" + this.syntheticPropertyName + "]"; } + } } diff --git a/source/java/org/alfresco/repo/search/impl/solr/facet/SolrFacetServiceImpl.java b/source/java/org/alfresco/repo/search/impl/solr/facet/SolrFacetServiceImpl.java index 32d742d0f7..6dc1210fac 100644 --- a/source/java/org/alfresco/repo/search/impl/solr/facet/SolrFacetServiceImpl.java +++ b/source/java/org/alfresco/repo/search/impl/solr/facet/SolrFacetServiceImpl.java @@ -791,24 +791,25 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF if (propertyDefs != null) { - for (Map.Entry prop : propertyDefs.entrySet()) + for (final Map.Entry prop : propertyDefs.entrySet()) { - final Facetable propIsFacetable = prop.getValue().getFacetable(); + final PropertyDefinition propDef = prop.getValue(); + final Facetable propIsFacetable = propDef.getFacetable(); switch (propIsFacetable) { case TRUE: - result.add(prop.getValue()); + result.add(propDef); break; case FALSE: // The value is not facetable. Do nothing. break; case UNSET: // These values may be facetable. - final DataTypeDefinition datatype = prop.getValue().getDataType(); + final DataTypeDefinition datatype = propDef.getDataType(); if (isNumeric(datatype) || isDateLike(datatype) || isFacetableText(datatype)) { - result.add(prop.getValue()); + result.add(propDef); break; } break; @@ -822,7 +823,54 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF return result; } - // TODO Consider moving into dictionary code. + @Override public List getFacetableSyntheticProperties() + { + final List result = new ArrayList<>(); + + final List allContentClasses = CollectionUtils.flatten(dictionaryService.getAllAspects(), dictionaryService.getAllTypes()); + + for (QName contentClass : allContentClasses) + { + result.addAll(getFacetableSyntheticProperties(contentClass)); + } + + return result; + } + + @Override public List getFacetableSyntheticProperties(QName contentClass) + { + final List result = new ArrayList<>(); + + final Map propertyDefs = dictionaryService.getPropertyDefs(contentClass); + + if (propertyDefs != null) + { + for (final Map.Entry prop : propertyDefs.entrySet()) + { + final PropertyDefinition propDef = prop.getValue(); + + // Only properties of type cm:content can expand to synthetic properties. + if (DataTypeDefinition.CONTENT.equals(propDef.getDataType().getName())) + { + // We do not want to treat the cm:content property itself as facetable. + // It is a content URL whose value is not suitable for facetting. + // e.g. 2010/1/22/13/14/6e228904-d5d2-4a99-b7b1-8fe7c03c71f3.bin|mimetype=application/octet-stream|size=728|encoding=UTF-8|locale=en_GB_ + // + // However there are elements within that content URL which *are* facetable and are correctly treated as such by SOLR. + // As these are not actually Alfresco content properties, we must return artificial PropertyDefinition objects: + result.add(new SyntheticPropertyDefinition(propDef, "size", DataTypeDefinition.LONG)); + result.add(new SyntheticPropertyDefinition(propDef, "mimetype", DataTypeDefinition.TEXT)); + } + else + { + // Intentionally empty. Only cm:content's size and mimetype are currently supported. + } + } + } + + return result; + } + private boolean isNumeric(DataTypeDefinition datatype) { boolean result;