From 7547b695ac4dbada51d3612946d8717d38b1dd7e Mon Sep 17 00:00:00 2001 From: Jan Vonka Date: Wed, 19 Sep 2007 11:47:29 +0000 Subject: [PATCH] Dictionary optimisation: improve performance when getting sub classes and property defs git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6825 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repo/dictionary/DictionaryComponent.java | 31 +++++ .../repo/dictionary/DictionaryDAO.java | 14 ++ .../repo/dictionary/DictionaryDAOImpl.java | 129 +++++++++++++++--- .../repo/node/db/DbNodeServiceImpl.java | 4 +- .../lucene/LuceneCategoryServiceImpl.java | 10 +- .../search/impl/lucene/LuceneQueryParser.java | 31 +---- .../cmr/dictionary/DictionaryService.java | 26 ++++ 7 files changed, 189 insertions(+), 56 deletions(-) diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryComponent.java b/source/java/org/alfresco/repo/dictionary/DictionaryComponent.java index b5ba37ff3f..e9a2f22022 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryComponent.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryComponent.java @@ -126,6 +126,15 @@ public class DictionaryComponent implements DictionaryService, TenantDeployer } + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getSubTypes(org.alfresco.service.namespace.QName, boolean) + */ + public Collection getSubTypes(QName superType, boolean follow) + { + return dictionaryDAO.getSubTypes(superType, follow); + } + + /* (non-Javadoc) * @see org.alfresco.repo.dictionary.DictionaryService#getTypes(org.alfresco.repo.ref.QName) */ @@ -155,6 +164,15 @@ public class DictionaryComponent implements DictionaryService, TenantDeployer } + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getSubAspects(org.alfresco.service.namespace.QName, boolean) + */ + public Collection getSubAspects(QName superAspect, boolean follow) + { + return dictionaryDAO.getSubAspects(superAspect, follow); + } + + /* (non-Javadoc) * @see org.alfresco.repo.dictionary.DictionaryService#getAspects(org.alfresco.repo.ref.QName) */ @@ -278,6 +296,19 @@ public class DictionaryComponent implements DictionaryService, TenantDeployer } return propDef; } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getPropertyDefs(org.alfresco.service.namespace.QName) + */ + public Map getPropertyDefs(QName className) + { + ClassDefinition classDef = dictionaryDAO.getClass(className); + if (classDef != null) + { + return classDef.getProperties(); + } + return null; + } /* (non-Javadoc) diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java b/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java index 3e2edbfebd..b70d9b74e1 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryDAO.java @@ -65,12 +65,26 @@ public interface DictionaryDAO extends ModelQuery * @return the types of the model */ public Collection getTypes(QName model); + + /** + * @param superType + * @param follow true => follow up the super-class hierarchy, false => immediate sub types only + * @return + */ + public Collection getSubTypes(QName superType, boolean follow); /** * @param model the model to retrieve aspects for * @return the aspects of the model */ public Collection getAspects(QName model); + + /** + * @param superAspect + * @param follow true => follow up the super-class hierarchy, false => immediate sub aspects only + * @return + */ + public Collection getSubAspects(QName superAspect, boolean follow); /** * @param model the model for which to get properties for diff --git a/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java b/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java index a2aff42336..f84ac8022a 100644 --- a/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java +++ b/source/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java @@ -511,6 +511,54 @@ public class DictionaryDAOImpl implements DictionaryDAO } return null; } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryDAO#getSubTypes(org.alfresco.service.namespace.QName, boolean) + */ + public Collection getSubTypes(QName superType, boolean follow) + { + // note: could be optimised further, if compiled into the model + + // Get all types (with parent type) for all models + Map allTypesAndParents = new HashMap(); // name, parent + + for (CompiledModel model : getCompiledModels().values()) + { + for (TypeDefinition type : model.getTypes()) + { + allTypesAndParents.put(type.getName(), type.getParentName()); + } + } + + // Get sub types + HashSet subTypes = new HashSet(); + for (QName type : allTypesAndParents.keySet()) + { + if (follow) + { + // all sub types + QName current = type; + while ((current != null) && !current.equals(superType)) + { + current = allTypesAndParents.get(current); // get parent + } + if (current != null) + { + subTypes.add(type); + } + } + else + { + // immediate sub types only + if (allTypesAndParents.get(type).equals(superType)) + { + subTypes.add(type); + } + } + + } + return subTypes; + } /* (non-Javadoc) @@ -529,6 +577,53 @@ public class DictionaryDAOImpl implements DictionaryDAO } return null; } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryDAO#getSubAspects(org.alfresco.service.namespace.QName, boolean) + */ + public Collection getSubAspects(QName superAspect, boolean follow) + { + // note: could be optimised further, if compiled into the model + + // Get all aspects (with parent aspect) for all models + Map allAspectsAndParents = new HashMap(); // name, parent + + for (CompiledModel model : getCompiledModels().values()) + { + for (AspectDefinition aspect : model.getAspects()) + { + allAspectsAndParents.put(aspect.getName(), aspect.getParentName()); + } + } + + // Get sub aspects + HashSet subAspects = new HashSet(); + for (QName aspect : allAspectsAndParents.keySet()) + { + if (follow) + { + // all sub aspects + QName current = aspect; + while ((current != null) && !current.equals(superAspect)) + { + current = allAspectsAndParents.get(current); // get parent + } + if (current != null) + { + subAspects.add(aspect); + } + } + else + { + // immediate sub aspects only + if (allAspectsAndParents.get(aspect).equals(superAspect)) + { + subAspects.add(aspect); + } + } + } + return subAspects; + } /* (non-Javadoc) @@ -608,34 +703,32 @@ public class DictionaryDAOImpl implements DictionaryDAO * @see org.alfresco.repo.dictionary.impl.DictionaryDAO#getModels() */ public Collection getModels() + { + return getCompiledModels().keySet(); + } + + // return all tenant-specific models and all shared (non-overridden) models + private Map getCompiledModels() { String tenantDomain = tenantService.getCurrentUserDomain(); if (tenantDomain != "") { // return all tenant-specific models and all shared (non-overridden) models - Collection filteredModels = new ArrayList(); - Collection tenantModels = new ArrayList(); - Collection nontenantModels = new ArrayList(); - + Map filteredModels = new HashMap(); + // get tenant models (if any) - for (QName key : getCompiledModels(tenantDomain).keySet()) - { - tenantModels.add(key); - } + Map tenantModels = getCompiledModels(tenantDomain); // get non-tenant models (if any) // note: these will be shared, if not overridden - could be core/system model or additional custom model shared between tenants - for (QName key : getCompiledModels("").keySet()) - { - nontenantModels.add(key); - } + Map nontenantModels = getCompiledModels(""); // check for overrides - filteredModels.addAll(nontenantModels); - - for (QName tenantModel : tenantModels) + filteredModels.putAll(nontenantModels); + + for (QName tenantModel : tenantModels.keySet()) { - for (QName nontenantModel : nontenantModels) + for (QName nontenantModel : nontenantModels.keySet()) { if (tenantModel.equals(nontenantModel)) { @@ -646,12 +739,12 @@ public class DictionaryDAOImpl implements DictionaryDAO } } - filteredModels.addAll(tenantModels); + filteredModels.putAll(tenantModels); return filteredModels; } else { - return getCompiledModels("").keySet(); + return getCompiledModels(""); } } diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java index 4e4fdbe769..95c10f5113 100644 --- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java @@ -970,6 +970,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl private Map getPropertiesImpl(Node node) throws InvalidNodeRefException { + Map propDefs = dictionaryService.getPropertyDefs(node.getTypeQName()); + Map nodeProperties = node.getProperties(); Map ret = new HashMap(nodeProperties.size()); // copy values @@ -978,7 +980,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl QName propertyQName = entry.getKey(); PropertyValue propertyValue = entry.getValue(); // get the property definition - PropertyDefinition propertyDef = dictionaryService.getProperty(propertyQName); + PropertyDefinition propertyDef = propDefs.get(propertyQName); if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.NODE_REF)) && (propertyValue != null) && (propertyValue.getStringValue() != null)) diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java index 97b1b132bb..32c93b990f 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java @@ -305,15 +305,7 @@ public class LuceneCategoryServiceImpl implements CategoryService public Collection getClassificationAspects() { - List list = new ArrayList(); - for (QName aspect : dictionaryService.getAllAspects()) - { - if (dictionaryService.isSubClass(aspect, ContentModel.ASPECT_CLASSIFIABLE)) - { - list.add(aspect); - } - } - return list; + return dictionaryService.getSubAspects(ContentModel.ASPECT_CLASSIFIABLE, true); } public NodeRef createClassifiction(StoreRef storeRef, QName typeName, String attributeName) diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java index c8a998fb20..792fcbe577 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java @@ -341,20 +341,7 @@ public class LuceneQueryParser extends QueryParser { throw new SearcherException("Invalid type: " + queryText); } - QName targetQName = target.getName(); - HashSet subclasses = new HashSet(); - for (QName classRef : dictionaryService.getAllTypes()) - { - TypeDefinition current = dictionaryService.getType(classRef); - while ((current != null) && !current.getName().equals(targetQName)) - { - current = (current.getParentName() == null) ? null : dictionaryService.getType(current.getParentName()); - } - if (current != null) - { - subclasses.add(classRef); - } - } + Collection subclasses = dictionaryService.getSubTypes(target.getName(), true); BooleanQuery booleanQuery = new BooleanQuery(); for (QName qname : subclasses) { @@ -420,21 +407,9 @@ public class LuceneQueryParser extends QueryParser } } - QName targetQName = target.getName(); - HashSet subclasses = new HashSet(); - for (QName classRef : dictionaryService.getAllAspects()) - { - AspectDefinition current = dictionaryService.getAspect(classRef); - while ((current != null) && !current.getName().equals(targetQName)) - { - current = (current.getParentName() == null) ? null : dictionaryService.getAspect(current.getParentName()); - } - if (current != null) - { - subclasses.add(classRef); - } - } + Collection subclasses = dictionaryService.getSubAspects(target.getName(), true); + BooleanQuery booleanQuery = new BooleanQuery(); for (QName qname : subclasses) { diff --git a/source/java/org/alfresco/service/cmr/dictionary/DictionaryService.java b/source/java/org/alfresco/service/cmr/dictionary/DictionaryService.java index 03a72b4a57..ef007ed2ed 100644 --- a/source/java/org/alfresco/service/cmr/dictionary/DictionaryService.java +++ b/source/java/org/alfresco/service/cmr/dictionary/DictionaryService.java @@ -25,6 +25,7 @@ package org.alfresco.service.cmr.dictionary; import java.util.Collection; +import java.util.Map; import org.alfresco.service.NotAuditable; import org.alfresco.service.PublicService; @@ -94,6 +95,14 @@ public interface DictionaryService @NotAuditable Collection getAllTypes(); + /** + * @param type + * @param follow true => follow up the super-class hierarchy, false => immediate sub types only + * @return the sub types of specified type + */ + @NotAuditable + Collection getSubTypes(QName type, boolean follow); + /** * @param model the model to retrieve types for * @return the names of all types defined within the specified model @@ -125,6 +134,14 @@ public interface DictionaryService @NotAuditable Collection getAllAspects(); + /** + * @param aspect + * @param follow true => follow up the super-class hierarchy, false => immediate sub aspects only + * @return the sub aspects of specified aspect + */ + @NotAuditable + Collection getSubAspects(QName aspect, boolean follow); + /** * @param model the model to retrieve aspects for * @return the names of all aspects defined within the specified model @@ -168,6 +185,15 @@ public interface DictionaryService */ @NotAuditable PropertyDefinition getProperty(QName className, QName propertyName); + + /** + * Gets the definitions of the properties defined by the specified Class. + * + * @param className the class name + * @return the property definitions + */ + @NotAuditable + Map getPropertyDefs(QName className); /** * Gets the definition of the property as defined by its owning Class.