Ard Schrijvers pushed to branch feature/translations-psp1 at cms / 
hippo-repository


Commits:
66b8c3f2 by Ard Schrijvers at 2016-02-17T17:06:54+01:00
REPO-1426 Make sure that the custom indexing now indexes on document level the 
hippo:name from the handle

Before, the hippo:translation nodes where used for indexing on document scope. 
Since this functionality has moved to the handle, we now need to index the 
hippo:name from the handle. Added unit tests to confirm this

- - - - -


5 changed files:

- api/src/main/java/org/hippoecm/repository/api/HippoNodeType.java
- 
engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingIndexingConfiguration.java
- 
engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingIndexingConfigurationImpl.java
- 
engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingSearchIndex.java
- engine/src/test/java/org/hippoecm/repository/FreeTextSearchTest.java


Changes:

=====================================
api/src/main/java/org/hippoecm/repository/api/HippoNodeType.java
=====================================
--- a/api/src/main/java/org/hippoecm/repository/api/HippoNodeType.java
+++ b/api/src/main/java/org/hippoecm/repository/api/HippoNodeType.java
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2008-2015 Hippo B.V. (http://www.onehippo.com)
+ *  Copyright 2008-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.
@@ -158,8 +158,16 @@ public interface HippoNodeType {
 
     public static final String NT_TEMPLATETYPE = "hipposysedit:templatetype";
 
+    /**
+     * @deprecated since REPO 4.0.0 (CMS 11.0)
+     */
+    @Deprecated
     public static final String NT_TRANSLATED = "hippo:translated";
 
+    /**
+     * @deprecated since REPO 4.0.0 (CMS 11.0)
+     */
+    @Deprecated
     public static final String NT_TRANSLATION = "hippo:translation";
 
     @Deprecated
@@ -284,6 +292,10 @@ public interface HippoNodeType {
 
     public static final String HIPPO_MEMBERS = "hipposys:members";
 
+    /**
+     * @deprecated since REPO 4.0.0 (CMS 11.0)
+     */
+    @Deprecated
     public static final String HIPPO_MESSAGE = "hippo:message";
 
     public static final String HIPPO_MANDATORY = "hipposysedit:mandatory";
@@ -368,6 +380,10 @@ public interface HippoNodeType {
 
     public static final String HIPPO_TEMPLATE = "hipposysedit:template";
 
+    /**
+     * @deprecated since REPO 4.0.0 (CMS 11.0)
+     */
+    @Deprecated
     public static final String HIPPO_TRANSLATION = "hippo:translation";
 
     public static final String HIPPOSYS_TYPE = "hipposys:type";


=====================================
engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingIndexingConfiguration.java
=====================================
--- 
a/engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingIndexingConfiguration.java
+++ 
b/engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingIndexingConfiguration.java
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2008-2013 Hippo B.V. (http://www.onehippo.com)
+ *  Copyright 2008-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.
@@ -49,21 +49,19 @@ public interface ServicingIndexingConfiguration extends 
IndexingConfiguration {
     Name getHippoDocumentName();
 
     /**
-     * @return QName of hippo:translation
+     * @return QName for hippo:named mixin
      */
-    Name getHippoTranslationName();
+    Name getHippoNamedName();
 
     /**
-     * @return QName of hippo:message
+     * @return QName fir hippo:name property
      */
-    Name getHippoMessageName();
-
-    String getTranslationMessageFieldName();
+    Name getHippoNameName();
 
     /**
-     * @return QName of hippo:translated
+     * @return the Lucene field name for {@link #getHippoNameName()}
      */
-    Name getHippoTranslatedName();
+    String getHippoNameFieldName();
 
     /**
      * @return QName of the hippo:paths property


=====================================
engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingIndexingConfigurationImpl.java
=====================================
--- 
a/engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingIndexingConfigurationImpl.java
+++ 
b/engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingIndexingConfigurationImpl.java
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2008-2013 Hippo B.V. (http://www.onehippo.com)
+ *  Copyright 2008-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.
@@ -35,7 +35,6 @@ import 
org.apache.jackrabbit.spi.commons.conversion.NameResolver;
 import org.apache.jackrabbit.spi.commons.conversion.ParsingNameResolver;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
-import org.hippoecm.repository.api.HippoNodeType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Attr;
@@ -45,6 +44,14 @@ import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
+import static org.hippoecm.repository.api.HippoNodeType.HIPPO_NAME;
+import static org.hippoecm.repository.api.HippoNodeType.HIPPO_PATHS;
+import static org.hippoecm.repository.api.HippoNodeType.HIPPO_TEXT;
+import static org.hippoecm.repository.api.HippoNodeType.NT_DOCUMENT;
+import static org.hippoecm.repository.api.HippoNodeType.NT_HANDLE;
+import static org.hippoecm.repository.api.HippoNodeType.NT_NAMED;
+import static org.hippoecm.repository.api.HippoNodeType.NT_SKIPINDEX;
+
 public class ServicingIndexingConfigurationImpl extends 
IndexingConfigurationImpl implements ServicingIndexingConfiguration {
 
 
@@ -73,13 +80,11 @@ public class ServicingIndexingConfigurationImpl extends 
IndexingConfigurationImp
 
     private Name hippoDocument;
 
-    private Name hippoTranslation;
-
-    private Name hippoMessage;
+    private Name hippoNamed;
 
-    private Name hippoTranslated;
+    private Name hippoName;
 
-    private String translationMessageFieldName;
+    private String hippoNameFieldName;
 
     /**
      * QName's of all the child node that should be aggregated
@@ -191,16 +196,15 @@ public class ServicingIndexingConfigurationImpl extends 
IndexingConfigurationImp
             }
 
         }
-        hippoPath = nameResolver.getQName(HippoNodeType.HIPPO_PATHS);
-        hippoText = nameResolver.getQName(HippoNodeType.HIPPO_TEXT);
-        hippoHandle = nameResolver.getQName(HippoNodeType.NT_HANDLE);
-        hippoDocument = nameResolver.getQName(HippoNodeType.NT_DOCUMENT);
-        hippoTranslation = 
nameResolver.getQName(HippoNodeType.HIPPO_TRANSLATION);
-        hippoMessage = nameResolver.getQName(HippoNodeType.HIPPO_MESSAGE);
-        hippoTranslated = nameResolver.getQName(HippoNodeType.NT_TRANSLATED);
-        skipIndex = nameResolver.getQName(HippoNodeType.NT_SKIPINDEX);
+        hippoPath = nameResolver.getQName(HIPPO_PATHS);
+        hippoText = nameResolver.getQName(HIPPO_TEXT);
+        hippoHandle = nameResolver.getQName(NT_HANDLE);
+        hippoDocument = nameResolver.getQName(NT_DOCUMENT);
+        hippoNamed = nameResolver.getQName(NT_NAMED);
+        hippoName = nameResolver.getQName(HIPPO_NAME);
+        hippoNameFieldName = nameResolver.getJCRName(hippoName);
+        skipIndex = nameResolver.getQName(NT_SKIPINDEX);
         hippoAggregates = idxHippoAggregates.toArray(new 
Name[idxHippoAggregates.size()]);
-        translationMessageFieldName = 
nameResolver.getJCRName(hippoTranslation) + "/" + 
nameResolver.getJCRName(hippoMessage);
         aggregateRules = super.getAggregateRules();
         if (aggregateRules == null) {
             aggregateRules = new AggregateRule[0];
@@ -306,24 +310,20 @@ public class ServicingIndexingConfigurationImpl extends 
IndexingConfigurationImp
         return hippoDocument;
     }
 
-    @Override
-    public Name getHippoTranslationName() {
-        return hippoTranslation;
-    }
 
     @Override
-    public Name getHippoMessageName() {
-        return hippoMessage;
+    public Name getHippoNamedName() {
+        return hippoNamed;
     }
 
     @Override
-    public Name getHippoTranslatedName() {
-        return hippoTranslated;
+    public Name getHippoNameName() {
+        return hippoName;
     }
 
     @Override
-    public String getTranslationMessageFieldName() {
-        return translationMessageFieldName;
+    public String getHippoNameFieldName() {
+        return hippoNameFieldName;
     }
 
     public Name getHippoPathPropertyName() {


=====================================
engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingSearchIndex.java
=====================================
--- 
a/engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingSearchIndex.java
+++ 
b/engine/src/main/java/org/hippoecm/repository/query/lucene/ServicingSearchIndex.java
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2008-2015 Hippo B.V. (http://www.onehippo.com)
+ *  Copyright 2008-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.
@@ -395,105 +395,108 @@ public class ServicingSearchIndex extends SearchIndex 
implements HippoQueryHandl
 
     @Override
     public void updateNodes(Iterator<NodeId> remove, Iterator<NodeState> add) 
throws RepositoryException, IOException {
-        Map<NodeId, NodeState> includedNodeStates = new HashMap<>();
-        // since NodeState does not have hashcode/equals impls, we need to use 
NodeId for caches
-        Set<NodeId> excludedIdsCache = new HashSet<>();
-        Set<NodeId> includedIdsCache = new HashSet<>();
+
+        final Set<NodeId> augmentedRemove = new HashSet<>();
+        while (remove.hasNext()) {
+            augmentedRemove.add(remove.next());
+        }
+
+        // NodeState does not implement equals hence we need NodeId
+        final Map<NodeId, NodeState> augmentedAdd = new HashMap<>();
         while (add.hasNext()) {
-            NodeState state = add.next();
-            if (state != null) {
-                if (!skipIndexing(state, excludedIdsCache, includedIdsCache)) {
-                    includedNodeStates.put(state.getNodeId(), state);
-                } else {
-                    log.debug("Nodestate '{}' is marked to be skipped for 
indexing.", state.getId());
-                }
-            }
+            final NodeState nodeState = add.next();
+            // since NodeState does not have hashcode/equals impls, we need to 
use NodeId for equals in Map
+            augmentedAdd.put(nodeState.getNodeId(), nodeState);
         }
 
-        NodeIdsNodeStatesHolder augmentedNodeIdsNodeStatesHolder = new 
NodeIdsNodeStatesHolder(remove, includedNodeStates);
-        augmentDocumentsToUpdate(augmentedNodeIdsNodeStatesHolder);
+        
appendDocumentsThatHaveChangedChildNodesOrChangedHandles(augmentedRemove, 
augmentedAdd);
 
-        super.updateNodes(augmentedNodeIdsNodeStatesHolder.remove.iterator(),
-                augmentedNodeIdsNodeStatesHolder.add.values().iterator());
+        //  now filter out documents that have a 'skip index' marker
+        Map<NodeId, NodeState> includedNodeStates = 
getSkipIndexFilteredNodeStates(augmentedAdd);
 
-    }
+        super.updateNodes(augmentedRemove.iterator(),
+                includedNodeStates.values().iterator());
 
-    private void augmentDocumentsToUpdate(final NodeIdsNodeStatesHolder 
augmentedNodeIdsNodeStatesHolder) throws IOException, RepositoryException {
-        appendContainingDocumentStates(augmentedNodeIdsNodeStatesHolder);
-        appendDocumentsForTranslations(augmentedNodeIdsNodeStatesHolder);
     }
 
-    private void appendDocumentsForTranslations(NodeIdsNodeStatesHolder 
nodeIdsNodeStatesHolder) throws IOException, RepositoryException {
-        List<NodeState> toAdd = new ArrayList<>();
-        for (Map.Entry<NodeId, NodeState> addEntry : 
nodeIdsNodeStatesHolder.add.entrySet()) {
-            final NodeState addedState = addEntry.getValue();
-            if (!isTranslation(addedState.getNodeTypeName())) {
-                continue;
-            }
-            try {
-                final NodeId parentId = addedState.getParentId();
-                if (parentId == null) {
-                    continue;
-                }
-                final NodeState parentState = getNodeState(parentId);
-                if (!isHandle(parentState)) {
-                    continue;
-                }
-                for (ChildNodeEntry siblingNodeEntry : 
parentState.getChildNodeEntries()) {
-                    final NodeId siblingId = siblingNodeEntry.getId();
-
-                    if(nodeIdsNodeStatesHolder.add.containsKey(siblingId) ||
-                            
nodeIdsNodeStatesHolder.remove.contains(siblingId)) {
-                        continue;
-                    }
-
-                    final NodeState siblingState = getNodeState(siblingId);
-                    if (!isHippoDocument(siblingState)) {
-                        continue;
-                    }
+    private Map<NodeId, NodeState> getSkipIndexFilteredNodeStates(final 
Map<NodeId, NodeState> augmentedAdd) throws RepositoryException {
+        Map<NodeId, NodeState> includedNodeStates = new HashMap<>();
+        // since NodeState does not have hashcode/equals impls, we need to use 
NodeId for caches
+        Set<NodeId> excludedIdsCache = new HashSet<>();
+        Set<NodeId> includedIdsCache = new HashSet<>();
 
-                    if(nodeIdsNodeStatesHolder.add.containsKey(siblingId) ||
-                            
nodeIdsNodeStatesHolder.remove.contains(siblingId)) {
-                        continue;
-                    }
-                    toAdd.add(siblingState);
+        for (NodeState nodeState : augmentedAdd.values()) {
+            if (nodeState != null) {
+                if (!skipIndexing(nodeState, excludedIdsCache, 
includedIdsCache)) {
+                    includedNodeStates.put(nodeState.getNodeId(), nodeState);
+                } else {
+                    log.debug("Nodestate '{}' is marked to be skipped for 
indexing.", nodeState.getId());
                 }
-            } catch (ItemStateException e) {
-                log.debug("Unable to retrieve state: {}", e.getMessage());
             }
         }
-        for (NodeState nodeState : toAdd) {
-            nodeIdsNodeStatesHolder.add.put(nodeState.getNodeId(), nodeState);
-            nodeIdsNodeStatesHolder.remove.add(nodeState.getNodeId());
-        }
+        return includedNodeStates;
     }
 
     /*
-     * If node states have been updated that are descendants of hippo:document 
nodes, then those hippo:document
-     * nodes need to be re-indexed.
+     * If node states (below documents) have been newly ADDED (can not yet be 
found via retrieveAggregateRoot
+     * since no 
org.apache.jackrabbit.core.query.lucene.FieldNames.AGGREGATED_NODE_UUID indexed 
on document level )
+     * that are descendants of hippo:document nodes, then those hippo:document 
nodes need to be re-indexed.
+     *
+     * Also re-index documents below changed handles
      */
-    private void appendContainingDocumentStates(NodeIdsNodeStatesHolder 
nodeIdsNodeStatesHolder) throws RepositoryException, IOException {
+    private void 
appendDocumentsThatHaveChangedChildNodesOrChangedHandles(final Set<NodeId> 
augmentedRemove,
+                                                                          
final Map<NodeId, NodeState> augmentedAdd) throws RepositoryException, 
IOException {
         final Set<NodeId> checkedIds = new HashSet<>();
-        List<NodeState> toAdd = new ArrayList<>();
-        for (Map.Entry<NodeId, NodeState> addEntry : 
nodeIdsNodeStatesHolder.add.entrySet()) {
+        List<NodeState> nodeStatesToAdd = new ArrayList<>();
+        final ItemStateManager itemStateManager = getItemStateManager();
+        for (Map.Entry<NodeId, NodeState> addEntry : augmentedAdd.entrySet()) {
             try {
-                NodeState document = 
getContainingDocument(addEntry.getValue(), checkedIds);
-                if (document != null) {
-                    final NodeId nodeId = document.getNodeId();
-                    if(nodeIdsNodeStatesHolder.add.containsKey(nodeId) ||
-                            nodeIdsNodeStatesHolder.remove.contains(nodeId)) {
-                        continue;
+                final NodeState state = addEntry.getValue();
+                if (isHandle(state)) {
+                    // changed handle (hippo:name translation perhaps, hence 
re-index the variants)
+                    for (ChildNodeEntry childNodeEntry : 
state.getChildNodeEntries()) {
+                        if (childNodeEntry.getId() instanceof HippoNodeId) {
+                            // do not index virtual child nodes, ever
+                            continue;
+                        }
+
+                        final NodeState childState = 
(NodeState)itemStateManager.getItemState(childNodeEntry.getId());
+                        if (isHippoDocument(childState)) {
+                            // found document below changed handle. Add 
document to be reindexed
+                            addStateIfNeeded(augmentedRemove, augmentedAdd, 
nodeStatesToAdd, childState);
+                        }
                     }
-                    toAdd.add(document);
+                    continue;
+                }
+
+                NodeState document = getContainingDocument(state, checkedIds, 
itemStateManager);
+                if (document != null) {
+                    addStateIfNeeded(augmentedRemove, augmentedAdd, 
nodeStatesToAdd, document);
+                    continue;
                 }
             } catch (ItemStateException e) {
                 log.debug("Unable to retrieve state: {}", e.getMessage());
             }
         }
-        for (NodeState nodeState : toAdd) {
-            nodeIdsNodeStatesHolder.add.put(nodeState.getNodeId(), nodeState);
-            nodeIdsNodeStatesHolder.remove.add(nodeState.getNodeId());
+        for (NodeState nodeState : nodeStatesToAdd) {
+            augmentedAdd.put(nodeState.getNodeId(), nodeState);
+            augmentedRemove.add(nodeState.getNodeId());
+        }
+    }
+
+    private void addStateIfNeeded(final Set<NodeId> augmentedRemove,
+                                  final Map<NodeId, NodeState> augmentedAdd,
+                                  final List<NodeState> nodeStates, final 
NodeState state) {
+        final NodeId nodeId = state.getNodeId();
+        if (nodeId instanceof HippoNodeId) {
+            // do not index virtual child nodes, ever
+            return;
         }
+        if (augmentedAdd.containsKey(nodeId) ||
+                augmentedRemove.contains(nodeId)) {
+            return;
+        }
+        nodeStates.add(state);
     }
 
     @Override
@@ -616,19 +619,15 @@ public class ServicingSearchIndex extends SearchIndex 
implements HippoQueryHandl
         return false;
     }
 
-    private boolean isHandle(NodeState node) {
+    private boolean isHandle(final NodeState node) {
         return 
node.getNodeTypeName().equals(getIndexingConfig().getHippoHandleName());
     }
 
-    private boolean isTranslated(NodeState state) {
-        return 
state.getMixinTypeNames().contains(getIndexingConfig().getHippoTranslatedName());
+    private boolean isTranslation(final NodeState state) {
+        return 
state.getMixinTypeNames().contains(getIndexingConfig().getHippoNamedName());
     }
 
-    private boolean isTranslation(Name name) {
-        return name.equals(getIndexingConfig().getHippoTranslationName());
-    }
-
-    private boolean isHippoDocument(NodeState node) {
+    private boolean isHippoDocument(final NodeState node) {
         try {
             final EffectiveNodeType nodeType = 
getContext().getNodeTypeRegistry().getEffectiveNodeType(node.getNodeTypeName());
             return 
nodeType.includesNodeType(getIndexingConfig().getHippoDocumentName());
@@ -642,7 +641,8 @@ public class ServicingSearchIndex extends SearchIndex 
implements HippoQueryHandl
      * @return the <code>NodeState</code> of the Document variant which is an 
ancestor of the state
      * or <code>null</code> if this state was not a child of a document variant
      */
-    private NodeState getContainingDocument(NodeState state, Set<NodeId> 
checkedIds) throws ItemStateException {
+    private NodeState getContainingDocument(final NodeState state, final 
Set<NodeId> checkedIds,
+                                            final ItemStateManager 
itemStateManager) throws ItemStateException {
         if (checkedIds.contains(state.getNodeId())) {
             // already checked these ancestors: no need to do it again
             return null;
@@ -651,24 +651,27 @@ public class ServicingSearchIndex extends SearchIndex 
implements HippoQueryHandl
         if (isDocumentVariant(state)) {
             return state;
         }
-        ItemStateManager ism = getItemStateManager();
         if (state.getParentId() == null) {
             return null;
         }
-        NodeState parent = (NodeState) ism.getItemState(state.getParentId());
+        NodeState parent = (NodeState) 
itemStateManager.getItemState(state.getParentId());
         if (parent == null) {
             return null;
 
         }
-        return getContainingDocument(parent, checkedIds);
+        return getContainingDocument(parent, checkedIds, itemStateManager);
     }
 
     /**
      * Adds the fulltext index field of the child states to Document doc
+     *
      * @param aggregateChildTypes When <code>true</code>, properties of child 
nodes will also be indexed as explicit
-     *                            fields on <code>doc</code> if configured as 
aggregate/childType in indexing_configuration.xml
+     *                            fields on <code>doc</code> if configured as 
aggregate/childType in
+     *                            indexing_configuration.xml
      */
-    private void aggregateDescendants(NodeState state, Document doc, 
IndexFormatVersion indexFormatVersion, ServicingNodeIndexer indexer,  boolean 
aggregateChildTypes) {
+    private void aggregateDescendants(final NodeState state, final Document 
doc,
+                                      final IndexFormatVersion 
indexFormatVersion,
+                                      final ServicingNodeIndexer indexer, 
final boolean aggregateChildTypes) {
         for (ChildNodeEntry childNodeEntry : state.getChildNodeEntries()) {
             if (childNodeEntry.getId() instanceof HippoNodeId) {
                 // do not index virtual child nodes, ever
@@ -753,25 +756,19 @@ public class ServicingSearchIndex extends SearchIndex 
implements HippoQueryHandl
             if (parentId == null) {
                 return;
             }
-            final NodeState parentState = getNodeState(parentId);
-            if (!isHandle(parentState) || !isTranslated(parentState)) {
+            final NodeState handleState = getNodeState(parentId);
+            if (!isHandle(handleState)) {
                 return;
             }
-            for (ChildNodeEntry childNodeEntry : 
parentState.getChildNodeEntries()) {
-                final Name childName = childNodeEntry.getName();
-                if (!isTranslation(childName)) {
-                    continue;
-                }
-                final NodeId translationId = childNodeEntry.getId();
-                final NodeState translationState = getNodeState(translationId);
-                final PropertyId messagePropertyId = new 
PropertyId(translationState.getNodeId(), 
getIndexingConfig().getHippoMessageName());
-                final PropertyState messagePropertyState = 
getPropertyState(messagePropertyId);
-                if (messagePropertyState.getValues().length == 0 || 
messagePropertyState.getValues()[0] == null || 
messagePropertyState.getValues()[0].getString().isEmpty()) {
-                    continue;
-                }
-                doc.add(new Field(FieldNames.AGGREGATED_NODE_UUID, 
translationId.toString(), Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS));
-                indexer.addStringValue(doc, 
getIndexingConfig().getTranslationMessageFieldName(), 
messagePropertyState.getValues()[0].getString(), true, true, 2.0f, true, false);
+            if (isTranslation(handleState)) {
+                final PropertyId namePropertyId = new 
PropertyId(handleState.getNodeId(), getIndexingConfig().getHippoNameName());
+                final PropertyState namePropertyState = 
getPropertyState(namePropertyId);
+                indexer.addStringValue(doc, 
getIndexingConfig().getHippoNameFieldName(), 
namePropertyState.getValues()[0].getString(), true, true, 2.0f, true, false);
+
             }
+            // make sure that if the handle gets the mixin 'hippo:named' or 
gets its 'hippo:name' changed, it triggers a re-index on the documents 
(variants)
+            doc.add(new Field(FieldNames.AGGREGATED_NODE_UUID, 
parentId.toString(), Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS));
+
         } catch (ItemStateException | RepositoryException e) {
             final String message = "Unable to add index translations of 
document " + state.getId();
             if (log.isDebugEnabled()) {
@@ -794,18 +791,4 @@ public class ServicingSearchIndex extends SearchIndex 
implements HippoQueryHandl
         return getContext().getItemStateManager();
     }
 
-    private class NodeIdsNodeStatesHolder {
-
-        Set<NodeId> remove = new HashSet<>();
-        // NodeState does not implement equals hence we need NodeId
-        Map<NodeId, NodeState> add = new HashMap<>();
-
-        NodeIdsNodeStatesHolder(Iterator<NodeId> remove, Map<NodeId, 
NodeState> add) {
-            while(remove.hasNext()) {
-                this.remove.add(remove.next());
-            }
-            this.add = add;
-        }
-    }
-
 }


=====================================
engine/src/test/java/org/hippoecm/repository/FreeTextSearchTest.java
=====================================
--- a/engine/src/test/java/org/hippoecm/repository/FreeTextSearchTest.java
+++ b/engine/src/test/java/org/hippoecm/repository/FreeTextSearchTest.java
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2008-2015 Hippo B.V. (http://www.onehippo.com)
+ *  Copyright 2008-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.
@@ -33,6 +33,8 @@ import org.hippoecm.repository.jackrabbit.RepositoryImpl;
 import org.junit.Test;
 import org.onehippo.repository.testutils.RepositoryTestCase;
 
+import static org.hippoecm.repository.api.HippoNodeType.HIPPO_NAME;
+import static org.hippoecm.repository.api.HippoNodeType.NT_NAMED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -80,18 +82,15 @@ public class FreeTextSearchTest extends RepositoryTestCase {
         resource.setProperty("jcr:data", new 
ByteArrayInputStream(data.toByteArray()));
         resource.setProperty("jcr:lastModified", Calendar.getInstance());
 
-        // set translation node
+        // set translation
         Node handle = session.getNode("/test/Document1");
-        handle.addMixin("hippo:translated");
-        final Node translation = handle.addNode("hippo:translation", 
"hippo:translation");
-        translation.setProperty("hippo:language", "en");
-        translation.setProperty("hippo:message", TRANSLATED_DOCUMENT_NAME);
+        handle.addMixin(NT_NAMED);
+        handle.setProperty(HIPPO_NAME, TRANSLATED_DOCUMENT_NAME);
 
         session.save();
         flushIndex(session.getRepository());
     }
-    
- 
+
     @Test
     public void testSimpleFreeTextSearch() throws Exception {
 
@@ -140,7 +139,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
      */
     @Test
     public void testSecondLevelChildNodeFreeTextSearch() throws Exception {
-        
+
         createContent(defaultContent);
         
         String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'"+HTML_CONTENT_PART+"')] 
order by @jcr:score descending";
@@ -163,7 +162,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
      */
     @Test
     public void testSecondChildNodeBinaryFreeTextSearch() throws Exception {
-        
+
         createContent(defaultContent);
         String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'"+BINARY_CONTENT_PART+"')]
 order by @jcr:score descending";
         QueryResult queryResult = 
session.getWorkspace().getQueryManager().createQuery(xpath, "xpath").execute();
@@ -178,6 +177,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
     }
     
     /**
+     * This test is to prove we require the FieldNames.AGGREGATED_NODE_UUID 
logic in ServicingSearchIndex
      * When we search on the text property of a direct child node below the 
hippo:document, we should
      * not find the hippo:document anymore when the child node is removed. 
This test is to assure that, 
      * when a direct child node is removed, the hippo:document is reindexed in 
the repository. 
@@ -187,7 +187,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
      */
     @Test
     public void testDeleteFirstLevelChildNode() throws Exception {
-        
+
         createContent(defaultContent);
         
         String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'"+COMPOUNDDOCUMENT_TITLE_PART+"')]
 order by @jcr:score descending";
@@ -214,6 +214,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
     }
     
     /**
+     * This test is to prove we require the FieldNames.AGGREGATED_NODE_UUID 
logic in ServicingSearchIndex
      * When we search on the text property of some child node at some level 
below the hippo:document, we should
      * not find the hippo:document anymore when the child node is removed. 
This test is to assure that, 
      * when a deeper located child node is removed, the hippo:document must is 
in the repository. 
@@ -223,7 +224,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
      */
     @Test
     public void testDeleteSecondLevelChildNode() throws Exception {
-        
+
         createContent(defaultContent);
         
         String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'"+HTML_CONTENT_PART+"')] 
order by @jcr:score descending";
@@ -236,6 +237,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
         
         Node n = session.getNode("/test/Document1/Document1/compoundchild");
         n.getNode("hippo:testhtml").remove();
+
         n.getSession().save();
         
         flushIndex(session.getRepository());
@@ -270,7 +272,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
             assertTrue(doc.getName().equals("Document1"));
         }
     }
-    
+
     @Test
     public void testAddSecondLevelChildNode() throws Exception {
         String word = "addedhtmlnode";
@@ -281,7 +283,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
         };
 
         createContent(defaultContent, extraSecondLevelChildNodeContent);
-        
+
         String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'"+word+"')] order by 
@jcr:score descending";
         QueryResult queryResult = 
session.getWorkspace().getQueryManager().createQuery(xpath, "xpath").execute();
         NodeIterator nodes = queryResult.getNodes();
@@ -291,6 +293,40 @@ public class FreeTextSearchTest extends RepositoryTestCase 
{
             assertTrue(doc.getName().equals("Document1"));
         }
     }
+
+    /**
+     * This test is to prove {@code 
}org.hippoecm.repository.query.lucene.ServicingSearchIndex#augmentDocumentsToUpdate}
 is
+     * really required. Namely a newly added node won't trigger a document 
reindex through 
org.apache.jackrabbit.core.query.lucene.FieldNames.AGGREGATED_NODE_UUID
+     */
+    @Test
+    public void testAddSecondLevelChildNode_to_existing_document() throws 
Exception {
+        String word = "addedhtmlnode";
+        createContent(defaultContent);
+
+        session.save();
+        flushIndex(session.getRepository());
+        {
+            String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'" + word + "')] order by 
@jcr:score descending";
+            QueryResult queryResult = 
session.getWorkspace().getQueryManager().createQuery(xpath, "xpath").execute();
+            NodeIterator nodes = queryResult.getNodes();
+            assertEquals(0L, nodes.getSize());
+        }
+        final Node html = 
session.getNode("/test/Document1/Document1/compoundchild").addNode("hippo:html2",
 "hippo:testhtml");
+        html.setProperty("hippo:testcontent", "The content property of 
testhtml node containing " + word);
+        session.save();
+        flushIndex(session.getRepository());
+
+        {
+            String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'" + word + "')] order by 
@jcr:score descending";
+            QueryResult queryResult = 
session.getWorkspace().getQueryManager().createQuery(xpath, "xpath").execute();
+            NodeIterator nodes = queryResult.getNodes();
+            assertEquals(1L, nodes.getSize());
+            while (nodes.hasNext()) {
+                Node doc = nodes.nextNode();
+                assertTrue(doc.getName().equals("Document1"));
+            }
+        }
+    }
     
     @Test
     public void testModifyFirstLevelChildNode() throws Exception {
@@ -322,6 +358,7 @@ public class FreeTextSearchTest extends RepositoryTestCase {
         Node html = 
session.getNode("/test/Document1/Document1/compoundchild/hippo:testhtml");
         String word = "changedtesthtml";
         html.setProperty("hippo:testcontent", "The content property of 
testhtml node now containing " + word);
+
         n.getSession().save();
         
         flushIndex(session.getRepository());
@@ -337,11 +374,10 @@ public class FreeTextSearchTest extends 
RepositoryTestCase {
     }
 
     /**
-     * All hippo:message properties of hippo:translation nodes under a handle 
are included
-     * in the fulltext index of the document.
+     * new style translation : hippo:name on handle must be indexed on 
document level
      */
     @Test
-    public void testSearchOnTranslatedDocumentName() throws Exception {
+    public void test_translation_SearchOnTranslatedDocumentName() throws 
Exception {
         createContent(defaultContent);
 
         String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'"+TRANSLATED_DOCUMENT_NAME+"')]
 order by @jcr:score descending";
@@ -352,20 +388,32 @@ public class FreeTextSearchTest extends 
RepositoryTestCase {
         assertEquals("/test/Document1/Document1", node.getPath());
     }
 
-    /**
-     * When the hippo:translation node under a hippo:handle is removed the 
document's index is updated
-     */
     @Test
-    public void testRemoveTranslationUpdatesDocumentIndex() throws Exception {
+    public void 
test_translation_RemoveTranslation_andAddTranslation_UpdatesDocumentIndex() 
throws Exception {
         createContent(defaultContent);
-        session.getNode("/test/Document1/hippo:translation").remove();
+        final Node handle = session.getNode("/test/Document1");
+        handle.removeMixin(NT_NAMED);
         session.save();
         flushIndex(session.getRepository());
 
-        String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'"+TRANSLATED_DOCUMENT_NAME+"')]
 order by @jcr:score descending";
-        final QueryResult queryResult = 
session.getWorkspace().getQueryManager().createQuery(xpath, "xpath").execute();
-        final NodeIterator nodes = queryResult.getNodes();
-        assertEquals(0L, nodes.getSize());
+        {
+            String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'" + 
TRANSLATED_DOCUMENT_NAME + "')] order by @jcr:score descending";
+            final QueryResult queryResult = 
session.getWorkspace().getQueryManager().createQuery(xpath, "xpath").execute();
+            final NodeIterator nodes = queryResult.getNodes();
+            assertEquals(0L, nodes.getSize());
+        }
+
+        // again adding the translation should result in the document being 
found by TRANSLATED_DOCUMENT_NAME
+        handle.addMixin(NT_NAMED);
+        handle.setProperty(HIPPO_NAME, TRANSLATED_DOCUMENT_NAME);
+        session.save();
+        flushIndex(session.getRepository());
+        {
+            String xpath = 
"//element(*,hippo:testsearchdocument)[jcr:contains(.,'"+TRANSLATED_DOCUMENT_NAME+"')]
 order by @jcr:score descending";
+            final QueryResult queryResult = 
session.getWorkspace().getQueryManager().createQuery(xpath, "xpath").execute();
+            final NodeIterator nodes = queryResult.getNodes();
+            assertEquals(1L, nodes.getSize());
+        }
     }
 
     @Test



View it on GitLab: 
https://code.onehippo.org/cms/hippo-repository/commit/66b8c3f2f42cdfc89b66768a7c8c3cccdd67e133
_______________________________________________
Hippocms-svn mailing list
Hippocms-svn@lists.onehippo.org
https://lists.onehippo.org/mailman/listinfo/hippocms-svn

Reply via email to