Index: addon/frontend/src/main/java/org/onehippo/taxonomy/plugin/model/JcrTaxonomy.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- addon/frontend/src/main/java/org/onehippo/taxonomy/plugin/model/JcrTaxonomy.java (revision 57515) +++ addon/frontend/src/main/java/org/onehippo/taxonomy/plugin/model/JcrTaxonomy.java (revision ) @@ -1,5 +1,5 @@ /* - * Copyright 2009-2015 Hippo B.V. (http://www.onehippo.com) + * Copyright 2009-2016 Hippo B.V. (http://www.onehippo.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -177,6 +177,17 @@ } } + protected void loadAllCategories(final Node node) { + if (categories == null) { + categories = new TreeMap<>(); + try { + loadCategories(node); + } catch (RepositoryException ex) { + log.error("failed to load categories", ex); + } + } + } + private void loadCategories(final Node node) throws RepositoryException { if (node instanceof HippoNode) { @@ -233,5 +244,8 @@ return getNodeModel().hashCode() ^ 991; } + public Map getCategoriesMap() { + return categories; + } } Index: addon/frontend/src/main/java/org/onehippo/taxonomy/plugin/model/TaxonomyObject.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- addon/frontend/src/main/java/org/onehippo/taxonomy/plugin/model/TaxonomyObject.java (revision 57515) +++ addon/frontend/src/main/java/org/onehippo/taxonomy/plugin/model/TaxonomyObject.java (revision ) @@ -1,5 +1,5 @@ /* - * Copyright 2009-2015 Hippo B.V. (http://www.onehippo.com) + * Copyright 2009-2016 Hippo B.V. (http://www.onehippo.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.onehippo.taxonomy.plugin.model; import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; import javax.jcr.ItemNotFoundException; import javax.jcr.Node; @@ -29,6 +31,7 @@ import org.hippoecm.frontend.model.ocm.JcrObject; import org.hippoecm.repository.api.HippoNodeType; import org.hippoecm.repository.api.HippoSession; +import org.hippoecm.repository.util.NodeIterable; import org.onehippo.taxonomy.api.TaxonomyNodeTypes; import org.onehippo.taxonomy.plugin.ITaxonomyService; import org.onehippo.taxonomy.plugin.api.JcrCategoryFilter; @@ -46,6 +49,8 @@ private final ITaxonomyService taxonomyService; + private Map allCategories; + /** * Constructor */ @@ -119,7 +124,7 @@ taxonomyNode = taxonomyNode.getParent(); } JcrTaxonomy taxonomy = toTaxonomy(new JcrNodeModel(taxonomyNode), true); - if (taxonomy.getCategoryByKey(key) != null) { + if (taxonomy.getCategoryByKey(key) != null || categoryKeyExists(key)) { throw new TaxonomyException("Key " + key + " already exists"); } @@ -137,6 +142,46 @@ } return toCategory(new JcrNodeModel(child), true); + } + + //Checks if a key exists in any existing taxonomy + private boolean categoryKeyExists(String key) throws RepositoryException { + if (allCategories == null) { + allCategories = new TreeMap<>(); + } + + loadAllCategories(); + + JcrCategory category = allCategories.get(key); + if (category != null) { + Node node; + try { + node = category.getNode(); + if (node != null && node.getSession().itemExists(node.getPath())) { + return true; + } + } catch (RepositoryException e) { + log.error("failed to find category by key " + key, e); + } + } + return false; + } + + private void loadAllCategories() throws RepositoryException { + JcrNodeModel jcrNodeModel = this.getNodeModel(); + if (jcrNodeModel == null || jcrNodeModel.getNode() == null) { + return; + } + while (jcrNodeModel.getParentModel() != null && !jcrNodeModel.getNode().getPrimaryNodeType().getName().equals("hippotaxonomy:container")) { + jcrNodeModel = jcrNodeModel.getParentModel(); + } + for (Node handle : new NodeIterable(jcrNodeModel.getNode().getNodes())) { + for (Node taxonomyNode : new NodeIterable(handle.getNodes())) { + JcrTaxonomy taxonomy = toTaxonomy(new JcrNodeModel(taxonomyNode), true); + taxonomy.loadAllCategories(taxonomyNode); + allCategories.putAll(taxonomy.getCategoriesMap()); + } + } } // Factory methods to subclass, e.g. to customize node creation.