Performance tweaks for AVM Indexing.

Removed calls to getXXXPaths().
Changed mappings of properties and aspects on AVM Nodes to
favor get all calls. 
Added getAspects() and getNodeProperties() which take
AVMNodeDescriptors.
Used these in AVM Indexing to reduce the number of redundant full lookups.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6121 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park
2007-06-27 18:24:05 +00:00
parent dcca019090
commit 8aa69caee3
19 changed files with 446 additions and 266 deletions

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing
*/
package org.alfresco.repo.admin.patch.impl;
import java.util.Iterator;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.admin.patch.AbstractPatch;
import org.alfresco.repo.avm.AVMNodeProperty;
import org.alfresco.repo.avm.AVMNodePropertyDAO;
/**
* Patch more remapping AVM properties.
* @author britt
*/
public class AVMPropertiesPatch extends AbstractPatch
{
private static final String MSG_SUCCESS = "patch.AVMProperties.result";
private AVMNodePropertyDAO fAVMNodePropertyDAO;
public void setAvmNodePropertyDAO(AVMNodePropertyDAO dao)
{
fAVMNodePropertyDAO = dao;
}
/* (non-Javadoc)
* @see org.alfresco.repo.admin.patch.AbstractPatch#applyInternal()
*/
@Override
protected String applyInternal() throws Exception
{
Iterator<AVMNodeProperty> iter = fAVMNodePropertyDAO.iterate();
while (iter.hasNext())
{
AVMNodeProperty prop = iter.next();
prop.getNode().getProperties().put(prop.getName(), prop.getValue());
fAVMNodePropertyDAO.delete(prop.getNode(), prop.getName());
}
return I18NUtil.getMessage(MSG_SUCCESS);
}
}

View File

@@ -232,6 +232,14 @@ public class AVMLockingAwareService implements AVMService, ApplicationContextAwa
return fService.getAspects(version, path);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.avm.AVMService#getAspects(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
*/
public Set<QName> getAspects(AVMNodeDescriptor desc)
{
return fService.getAspects(desc);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.avm.AVMService#getCommonAncestor(org.alfresco.service.cmr.avm.AVMNodeDescriptor, org.alfresco.service.cmr.avm.AVMNodeDescriptor)
*/
@@ -249,6 +257,14 @@ public class AVMLockingAwareService implements AVMService, ApplicationContextAwa
return fService.getContentDataForRead(version, path);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.avm.AVMService#getContentDataForRead(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
*/
public ContentData getContentDataForRead(AVMNodeDescriptor desc)
{
return fService.getContentDataForRead(desc);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.avm.AVMService#getContentDataForWrite(java.lang.String)
*/
@@ -445,6 +461,14 @@ public class AVMLockingAwareService implements AVMService, ApplicationContextAwa
return fService.getNodeProperties(version, path);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.avm.AVMService#getNodeProperties(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
*/
public Map<QName, PropertyValue> getNodeProperties(AVMNodeDescriptor desc)
{
return fService.getNodeProperties(desc);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.avm.AVMService#getNodeProperty(int, java.lang.String, org.alfresco.service.namespace.QName)
*/

View File

@@ -235,4 +235,10 @@ public interface AVMNode
* @return A Set of Aspects names.
*/
public Set<QName> getAspects();
/**
* Add properties to those that already exist.
* @param properties The properties to add.
*/
public void addProperties(Map<QName, PropertyValue> properties);
}

View File

@@ -90,12 +90,15 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
*/
private Set<QName> fAspects;
private Map<QName, PropertyValue> fProperties;
/**
* Default constructor.
*/
protected AVMNodeImpl()
{
fAspects = new HashSet<QName>();
fProperties = new HashMap<QName, PropertyValue>();
}
/**
@@ -107,6 +110,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
AVMStore store)
{
fAspects = new HashSet<QName>();
fProperties = new HashMap<QName, PropertyValue>();
fID = id;
fVersionID = -1;
fIsRoot = false;
@@ -343,14 +347,10 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
*/
protected void copyProperties(AVMNode other)
{
Map<QName, PropertyValue> properties = other.getProperties();
for (QName name : properties.keySet())
fProperties = new HashMap<QName, PropertyValue>();
for (Map.Entry<QName, PropertyValue> entry : other.getProperties().entrySet())
{
AVMNodeProperty newProp = new AVMNodePropertyImpl();
newProp.setNode(this);
newProp.setName(name);
newProp.setValue(properties.get(name));
AVMDAOs.Instance().fAVMNodePropertyDAO.save(newProp);
fProperties.put(entry.getKey(), entry.getValue());
}
}
@@ -394,18 +394,15 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
{
checkReadOnly();
}
AVMNodeProperty prop = AVMDAOs.Instance().fAVMNodePropertyDAO.get(this, name);
if (prop != null)
fProperties.put(name, value);
}
public void addProperties(Map<QName, PropertyValue> properties)
{
for (Map.Entry<QName, PropertyValue> entry : properties.entrySet())
{
prop.setValue(value);
AVMDAOs.Instance().fAVMNodePropertyDAO.update(prop);
return;
fProperties.put(entry.getKey(), entry.getValue());
}
prop = new AVMNodePropertyImpl();
prop.setNode(this);
prop.setName(name);
prop.setValue(value);
AVMDAOs.Instance().fAVMNodePropertyDAO.save(prop);
}
/**
@@ -414,14 +411,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
*/
public void setProperties(Map<QName, PropertyValue> properties)
{
if (DEBUG)
{
checkReadOnly();
}
for (QName name : properties.keySet())
{
setProperty(name, properties.get(name));
}
fProperties = properties;
}
/**
@@ -431,12 +421,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
*/
public PropertyValue getProperty(QName name)
{
AVMNodeProperty prop = AVMDAOs.Instance().fAVMNodePropertyDAO.get(this, name);
if (prop == null)
{
return null;
}
return prop.getValue();
return fProperties.get(name);
}
/**
@@ -445,13 +430,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
*/
public Map<QName, PropertyValue> getProperties()
{
Map<QName, PropertyValue> retVal = new HashMap<QName, PropertyValue>();
List<AVMNodeProperty> props = AVMDAOs.Instance().fAVMNodePropertyDAO.get(this);
for (AVMNodeProperty prop : props)
{
retVal.put(prop.getName(), prop.getValue());
}
return retVal;
return fProperties;
}
/**
@@ -464,7 +443,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
{
checkReadOnly();
}
AVMDAOs.Instance().fAVMNodePropertyDAO.delete(this, name);
fProperties.remove(name);
}
/**
@@ -472,11 +451,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
*/
public void deleteProperties()
{
if (DEBUG)
{
checkReadOnly();
}
AVMDAOs.Instance().fAVMNodePropertyDAO.deleteAll(this);
fProperties.clear();
}
/**

View File

@@ -23,6 +23,7 @@
package org.alfresco.repo.avm;
import java.util.Iterator;
import java.util.List;
import org.alfresco.service.namespace.QName;
@@ -72,4 +73,10 @@ public interface AVMNodePropertyDAO
* @param name The name of the property to delete.
*/
public void delete(AVMNode node, QName name);
/**
* Get an iterator over all properties.
* @return
*/
public Iterator<AVMNodeProperty> iterate();
}

View File

@@ -106,7 +106,7 @@ public class AVMRepository
private AVMStorePropertyDAO fAVMStorePropertyDAO;
private ChildEntryDAO fChildEntryDAO;
// A bunch of TransactionListeners that do work for this.
/**
@@ -2677,4 +2677,39 @@ public class AVMRepository
components.remove(components.size() - 1);
}
}
public Map<QName, PropertyValue> getNodeProperties(AVMNodeDescriptor desc)
{
AVMNode node = fAVMNodeDAO.getByID(desc.getId());
if (node == null)
{
throw new AVMNotFoundException("Node not found: " + desc);
}
return node.getProperties();
}
public ContentData getContentDataForRead(AVMNodeDescriptor desc)
{
AVMNode node = fAVMNodeDAO.getByID(desc.getId());
if (node == null)
{
throw new AVMNotFoundException("Node not found: " + desc);
}
if (node.getType() == AVMNodeType.PLAIN_FILE)
{
PlainFileNode file = (PlainFileNode)node;
return file.getContentData();
}
throw new AVMWrongTypeException("Not a Plain File: " + desc);
}
public Set<QName> getAspects(AVMNodeDescriptor desc)
{
AVMNode node = fAVMNodeDAO.getByID(desc.getId());
if (node == null)
{
throw new AVMNotFoundException("Node not found: " + desc);
}
return node.getAspects();
}
}

View File

@@ -1068,6 +1068,18 @@ public class AVMServiceImpl implements AVMService
return fAVMRepository.getNodeProperties(version, path);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.avm.AVMService#getNodeProperties(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
*/
public Map<QName, PropertyValue> getNodeProperties(AVMNodeDescriptor desc)
{
if (desc == null)
{
throw new AVMBadArgumentException("Null descriptor.");
}
return fAVMRepository.getNodeProperties(desc);
}
/**
* Delete a property.
* @param path The path to the node.
@@ -1215,6 +1227,18 @@ public class AVMServiceImpl implements AVMService
return fAVMRepository.getContentDataForRead(version, path);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.avm.AVMService#getContentDataForRead(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
*/
public ContentData getContentDataForRead(AVMNodeDescriptor desc)
{
if (desc == null)
{
throw new AVMBadArgumentException("Null descriptor.");
}
return fAVMRepository.getContentDataForRead(desc);
}
/**
* Get the Content data for writing.
* @param path The path to the node.
@@ -1295,6 +1319,18 @@ public class AVMServiceImpl implements AVMService
return fAVMRepository.getAspects(version, path);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.avm.AVMService#getAspects(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
*/
public Set<QName> getAspects(AVMNodeDescriptor desc)
{
if (desc == null)
{
throw new AVMBadArgumentException("Null descriptor: " + desc);
}
return fAVMRepository.getAspects(desc);
}
/**
* Remove an aspect and its properties from a node.
* @param path The path to the node.

View File

@@ -101,6 +101,37 @@ import org.alfresco.util.Pair;
*/
public class AVMServiceTest extends AVMServiceTestBase
{
/**
* Test version by date lookup.
*/
public void testVersionByDate()
{
try
{
ArrayList<Long> times = new ArrayList<Long>();
BulkLoader loader = new BulkLoader();
loader.setAvmService(fService);
loader.recursiveLoad("source/java/org/alfresco/repo/avm", "main:/");
times.add(System.currentTimeMillis());
assertEquals(1, fService.createSnapshot("main", null, null).get("main").intValue());
loader.recursiveLoad("source/java/org/alfresco/repo/action", "main:/");
times.add(System.currentTimeMillis());
assertEquals(2, fService.createSnapshot("main", null, null).get("main").intValue());
loader.recursiveLoad("source/java/org/alfresco/repo/audit", "main:/");
times.add(System.currentTimeMillis());
assertEquals(3, fService.createSnapshot("main", null, null).get("main").intValue());
assertEquals(1, fService.getStoreVersions("main", null, new Date(times.get(0))).size());
assertEquals(3, fService.getStoreVersions("main", new Date(times.get(0)), null).size());
assertEquals(2, fService.getStoreVersions("main", new Date(times.get(1)),
new Date(System.currentTimeMillis())).size());
}
catch (Exception e)
{
e.printStackTrace(System.err);
fail();
}
}
/**
* Test properties.
*/
@@ -4992,36 +5023,6 @@ public class AVMServiceTest extends AVMServiceTestBase
}
}
/**
* Test version by date lookup.
*/
public void testVersionByDate()
{
try
{
ArrayList<Long> times = new ArrayList<Long>();
BulkLoader loader = new BulkLoader();
loader.setAvmService(fService);
loader.recursiveLoad("source/java/org/alfresco/repo/avm", "main:/");
times.add(System.currentTimeMillis());
assertEquals(1, fService.createSnapshot("main", null, null).get("main").intValue());
loader.recursiveLoad("source/java/org/alfresco/repo/action", "main:/");
times.add(System.currentTimeMillis());
assertEquals(2, fService.createSnapshot("main", null, null).get("main").intValue());
loader.recursiveLoad("source/java/org/alfresco/repo/audit", "main:/");
times.add(System.currentTimeMillis());
assertEquals(3, fService.createSnapshot("main", null, null).get("main").intValue());
assertEquals(1, fService.getStoreVersions("main", null, new Date(times.get(0))).size());
assertEquals(3, fService.getStoreVersions("main", new Date(times.get(0)), null).size());
assertEquals(2, fService.getStoreVersions("main", new Date(times.get(1)),
new Date(System.currentTimeMillis())).size());
}
catch (Exception e)
{
e.printStackTrace(System.err);
fail();
}
}
/**
* Test AVMStore functions.

View File

@@ -1058,7 +1058,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
throw new AVMNotFoundException("Path " + path + " not found.");
}
AVMNode node = lPath.getCurrentNode();
node.setProperties(properties);
node.addProperties(properties);
node.setGuid(GUID.generate());
}

View File

@@ -1,5 +1,7 @@
package org.alfresco.repo.avm;
import org.alfresco.service.cmr.repository.ContentData;
/**
* Interface for Plain file nodes.
* @author britt
@@ -17,4 +19,10 @@ interface PlainFileNode extends FileNode
* @param mimeType
*/
public void setMimeType(String mimeType);
/**
* Special case.
* @return
*/
public ContentData getContentData();
}

View File

@@ -129,7 +129,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode
setVersionID(versionID + 1);
AVMDAOs.Instance().fAVMNodeDAO.save(this);
AVMDAOs.Instance().fAVMNodeDAO.flush();
setProperties(props);
addProperties(props);
setAspects(new HashSet<QName>(aspects));
if (acl != null)
{
@@ -376,6 +376,14 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode
* @return The ContentData object for this file.
*/
public ContentData getContentData(Lookup lPath)
{
return getContentData();
}
/* (non-Javadoc)
* @see org.alfresco.repo.avm.PlainFileNode#getContentData()
*/
public ContentData getContentData()
{
return new ContentData(fContentURL, fMimeType, fLength, fEncoding);
}

View File

@@ -51,6 +51,22 @@
<key column="id"/>
<element type="QName" not-null="true" column="name" length="200"/>
</set>
<map name="properties" fetch="join" lazy="false" table="avm_node_properties_new" cascade="all" optimistic-lock="true">
<cache usage="read-write"/>
<key column="node_id" not-null="true"/>
<map-key type="QName" length="200" column="qname"/>
<composite-element class="org.alfresco.repo.domain.PropertyValue">
<property name="actualType" column="actual_type" type="string" length="15" not-null="true" />
<property name="multiValued" column="multi_valued" type="boolean" not-null="true" />
<property name="persistedType" column="persisted_type" type="string" length="15" not-null="true" />
<property name="booleanValue" column="boolean_value" type="boolean" />
<property name="longValue" column="long_value" type="long" />
<property name="floatValue" column="float_value" type="float" />
<property name="doubleValue" column="double_value" type="double" />
<property name="stringValue" column="string_value" type="string" length="1024"/>
<property name="serializableValue" column="serializable_value" type="serializable" length="16384"/>
</composite-element>
</map>
<!-- Deleted nodes -->
<subclass name="DeletedNodeImpl"
proxy="DeletedNode"

View File

@@ -1,5 +1,6 @@
package org.alfresco.repo.avm.hibernate;
import java.util.Iterator;
import java.util.List;
import org.alfresco.repo.avm.AVMNode;
@@ -91,4 +92,15 @@ class AVMNodePropertyDAOHibernate extends HibernateDaoSupport
delete.setParameter("name", name);
delete.executeUpdate();
}
/* (non-Javadoc)
* @see org.alfresco.repo.avm.AVMNodePropertyDAO#iterate()
*/
@SuppressWarnings("unchecked")
public Iterator<AVMNodeProperty> iterate()
{
Query query =
getSession().createQuery("from AVMNodePropertyImpl anp");
return (Iterator<AVMNodeProperty>)query.iterate();
}
}

View File

@@ -34,11 +34,9 @@ import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.i18n.I18NUtil;
@@ -115,8 +113,6 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
private ContentService contentService;
private Set<String> indexedPaths = new HashSet<String>();
private FTSIndexerAware callBack;
private FullTextSearchIndexer fullTextSearchIndexer;
@@ -378,197 +374,142 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
return docs;
}
String[] splitPathForDoc = splitPath(stringNodeRef);
String docStore = splitPathForDoc[0];
List<Pair<Integer, String>> allPaths = avmService.getPathsInStoreHead(desc, docStore);
List<Pair<Integer, String>> paths = new ArrayList<Pair<Integer, String>>();
for (Pair<Integer, String> pair : allPaths)
{
if (pair.getFirst().intValue() == endVersion)
{
paths.add(pair);
}
}
if (paths.size() == 0)
{
for (Pair<Integer, String> pair : allPaths)
{
if (pair.getFirst().intValue() == -1)
{
paths.add(pair);
}
}
}
if (paths.size() == 0)
{
return docs;
}
for (Pair<Integer, String> path : paths)
{
if (indexedPaths.contains(path.getSecond()))
{
return docs;
}
}
for (Pair<Integer, String> path : paths)
{
indexedPaths.add(path.getSecond());
}
// Naughty, Britt should come up with a fix that doesn't require this.
AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(desc.getId());
if (paths.size() > 0)
if (desc != null)
{
if (desc != null)
NodeRef nodeRef = AVMNodeConverter.ToNodeRef(endVersion, stringNodeRef);
Document xdoc = new Document();
xdoc.add(new Field("ID", nodeRef.toString(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("ID", stringNodeRef, Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("TX", AlfrescoTransactionSupport.getTransactionId(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
boolean isAtomic = true;
Map<QName, Serializable> properties = getIndexableProperties(desc, nodeRef, endVersion, stringNodeRef);
for (QName propertyName : properties.keySet())
{
NodeRef nodeRef = AVMNodeConverter.ToNodeRef(endVersion, stringNodeRef);
Document xdoc = new Document();
xdoc.add(new Field("ID", nodeRef.toString(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
for (Pair<Integer, String> path : paths)
Serializable value = properties.get(propertyName);
if (indexAllProperties)
{
String[] splitPath = splitPath(path.getSecond());
@SuppressWarnings("unused")
String pathInStore = splitPath[1];
xdoc.add(new Field("ID", path.getSecond(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
}
xdoc.add(new Field("TX", AlfrescoTransactionSupport.getTransactionId(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
boolean isAtomic = true;
Map<QName, Serializable> properties = getIndexableProperties(desc, nodeRef, endVersion, stringNodeRef);
for (QName propertyName : properties.keySet())
{
Serializable value = properties.get(propertyName);
if (indexAllProperties)
{
indexProperty(nodeRef, propertyName, value, xdoc, false, properties);
}
else
{
isAtomic &= indexProperty(nodeRef, propertyName, value, xdoc, true, properties);
}
}
StringBuilder qNameBuffer = new StringBuilder(64);
for (Pair<Integer, String> path : paths)
{
if (node.getIsRoot())
{
}
// pseudo roots?
else
{
String[] splitPath = splitPath(path.getSecond());
String store = splitPath[0];
String pathInStore = splitPath[1];
SimplePath simplePath = new SimplePath(pathInStore);
StringBuilder xpathBuilder = new StringBuilder();
for (int i = 0; i < simplePath.size(); i++)
{
xpathBuilder.append("/{}").append(simplePath.get(i));
}
String xpath = xpathBuilder.toString();
if (qNameBuffer.length() > 0)
{
qNameBuffer.append(";/");
}
// Get the parent
ArrayList<String> ancestors = new ArrayList<String>();
StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(store).append(":/");
ancestors.add(pathBuilder.toString());
boolean requiresSep = false;
for (int i = 0; i < simplePath.size() - 1; i++)
{
if (requiresSep)
{
pathBuilder.append("/");
}
else
{
requiresSep = true;
}
pathBuilder.append(simplePath.get(i));
ancestors.add(pathBuilder.toString());
}
qNameBuffer.append(ISO9075.getXPathName(QName.createQName("", simplePath.get(simplePath.size() - 1))));
xdoc.add(new Field("PARENT", ancestors.get(ancestors.size() - 1), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
// TODO: Categories and LINKASPECT
if (includeDirectoryDocuments)
{
if (desc.isDirectory())
{
// TODO: Exclude category paths
Document directoryEntry = new Document();
directoryEntry.add(new Field("ID", nodeRef.toString(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
directoryEntry.add(new Field("ID", path.getSecond(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
directoryEntry.add(new Field("PATH", xpath, Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO));
// Find all parent nodes.
for (String toAdd : ancestors)
{
directoryEntry.add(new Field("ANCESTOR", toAdd, Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
}
directoryEntry.add(new Field("ISCONTAINER", "T", Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
docs.add(directoryEntry);
}
}
}
}
if (node.getIsRoot())
{
// TODO: Does the root element have a QName?
xdoc.add(new Field("ISCONTAINER", "T", Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("PATH", "", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("QNAME", "", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("ISROOT", "T", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("ISNODE", "T", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
docs.add(xdoc);
indexProperty(nodeRef, propertyName, value, xdoc, false, properties);
}
else
// not a root node
{
xdoc.add(new Field("QNAME", qNameBuffer.toString(), Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO));
QName typeQName = getType(desc);
xdoc.add(new Field("TYPE", ISO9075.getXPathName(typeQName), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
for (QName classRef : avmService.getAspects(endVersion, stringNodeRef))
{
xdoc.add(new Field("ASPECT", ISO9075.getXPathName(classRef), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
}
xdoc.add(new Field("ISROOT", "F", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("ISNODE", "T", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
docs.add(xdoc);
isAtomic &= indexProperty(nodeRef, propertyName, value, xdoc, true, properties);
}
}
StringBuilder qNameBuffer = new StringBuilder(64);
if (node.getIsRoot())
{
}
// pseudo roots?
else
{
String[] splitPath = splitPath(stringNodeRef);
String store = splitPath[0];
String pathInStore = splitPath[1];
SimplePath simplePath = new SimplePath(pathInStore);
StringBuilder xpathBuilder = new StringBuilder();
for (int i = 0; i < simplePath.size(); i++)
{
xpathBuilder.append("/{}").append(simplePath.get(i));
}
String xpath = xpathBuilder.toString();
if (qNameBuffer.length() > 0)
{
qNameBuffer.append(";/");
}
// Get the parent
ArrayList<String> ancestors = new ArrayList<String>();
StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(store).append(":/");
ancestors.add(pathBuilder.toString());
boolean requiresSep = false;
for (int i = 0; i < simplePath.size() - 1; i++)
{
if (requiresSep)
{
pathBuilder.append("/");
}
else
{
requiresSep = true;
}
pathBuilder.append(simplePath.get(i));
ancestors.add(pathBuilder.toString());
}
qNameBuffer.append(ISO9075.getXPathName(QName.createQName("", simplePath.get(simplePath.size() - 1))));
xdoc.add(new Field("PARENT", ancestors.get(ancestors.size() - 1), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
// TODO: Categories and LINKASPECT
if (includeDirectoryDocuments)
{
if (desc.isDirectory())
{
// TODO: Exclude category paths
Document directoryEntry = new Document();
directoryEntry.add(new Field("ID", nodeRef.toString(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
directoryEntry.add(new Field("ID", stringNodeRef, Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
directoryEntry.add(new Field("PATH", xpath, Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO));
// Find all parent nodes.
for (String toAdd : ancestors)
{
directoryEntry.add(new Field("ANCESTOR", toAdd, Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
}
directoryEntry.add(new Field("ISCONTAINER", "T", Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
docs.add(directoryEntry);
}
}
}
if (node.getIsRoot())
{
// TODO: Does the root element have a QName?
xdoc.add(new Field("ISCONTAINER", "T", Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("PATH", "", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("QNAME", "", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("ISROOT", "T", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("ISNODE", "T", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
docs.add(xdoc);
}
else
// not a root node
{
xdoc.add(new Field("QNAME", qNameBuffer.toString(), Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.NO));
QName typeQName = getType(desc);
xdoc.add(new Field("TYPE", ISO9075.getXPathName(typeQName), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
for (QName classRef : avmService.getAspects(desc))
{
xdoc.add(new Field("ASPECT", ISO9075.getXPathName(classRef), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
}
xdoc.add(new Field("ISROOT", "F", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
xdoc.add(new Field("ISNODE", "T", Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
docs.add(xdoc);
}
}
else
{
@@ -612,7 +553,7 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
private Map<QName, Serializable> getIndexableProperties(AVMNodeDescriptor desc, NodeRef nodeRef, Integer version, String path)
{
Map<QName, PropertyValue> properties = avmService.getNodeProperties(version, path);
Map<QName, PropertyValue> properties = avmService.getNodeProperties(desc);
Map<QName, Serializable> result = new HashMap<QName, Serializable>();
for (QName qName : properties.keySet())
@@ -644,7 +585,15 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
{
try
{
ContentData contentData = avmService.getContentDataForRead(version, path);
ContentData contentData = null;
if (desc.isPlainFile())
{
contentData = avmService.getContentDataForRead(desc);
}
else
{
contentData = avmService.getContentDataForRead(endVersion, path);
}
result.put(ContentModel.PROP_CONTENT, contentData);
}
catch (AVMException e)

View File

@@ -987,6 +987,14 @@ public interface AVMService
*/
public Map<QName, PropertyValue> getNodeProperties(int version, String path);
/**
* Get all the properties associated with a node identified by a descriptor.
* @param desc The node descriptor
* @return A Map of the properties.
* @throws AVMNotFoundException
*/
public Map<QName, PropertyValue> getNodeProperties(AVMNodeDescriptor desc);
/**
* Delete a property.
*
@@ -1083,6 +1091,14 @@ public interface AVMService
*/
public ContentData getContentDataForRead(int version, String path);
/**
* Get ContentData using only a node descriptor.
* @param desc The node descriptor.
* @return The ContentData
* @throws AVMNotFoundException
*/
public ContentData getContentDataForRead(AVMNodeDescriptor desc);
/**
* <em>Low-level internal function</em>:&nbsp;&nbsp; Get the ContentData for
@@ -1137,6 +1153,13 @@ public interface AVMService
*/
public Set<QName> getAspects(int version, String path);
/**
* Get all the aspects from a node descriptor.
* @param desc The node descriptor.
* @return The Set of Aspects.
*/
public Set<QName> getAspects(AVMNodeDescriptor desc);
/**
* Remove an aspect and its properties from a node.
*