diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index 2886f3e156..73c9cf4df0 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -179,3 +179,6 @@ patch.customWebClientExtension.description=Adds Web Client Extension space to Da
patch.customWorkflowDefs.description=Adds Workflow Definitions space to Data Dictionary.
patch.emailContributorGroup.description=Adds the 'GROUP_EMAIL_CONTRIBUTORS' group.
+
+patch.avmStoreAsIdentifier.description=Reindex wca:webfolder to make wca:avmstore an identifier
+patch.avmStoreAsIdentifier.result=Reindexed wca:webfolder to make wca:avmstore an identifier
diff --git a/config/alfresco/model/dictionaryModel.xml b/config/alfresco/model/dictionaryModel.xml
index de4271bf9b..9bee7d365a 100644
--- a/config/alfresco/model/dictionaryModel.xml
+++ b/config/alfresco/model/dictionaryModel.xml
@@ -64,7 +64,7 @@
- org.alfresco.repo.search.impl.lucene.analysis.DateAnalyser
+ org.alfresco.repo.search.impl.lucene.analysis.DateTimeAnalyser
java.util.Date
diff --git a/config/alfresco/model/wcmAppModel.xml b/config/alfresco/model/wcmAppModel.xml
index b539cd0e0e..79060bd386 100644
--- a/config/alfresco/model/wcmAppModel.xml
+++ b/config/alfresco/model/wcmAppModel.xml
@@ -27,6 +27,11 @@
AVM Store Root
d:text
+
+ true
+ false
+ false
+
Default Webapp
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index 0e6315ab66..1007bebadd 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -1015,7 +1015,7 @@
alfresco/bootstrap/webScriptsReadme2.xml
-
+
patch.customWorkflowDefs
@@ -1059,4 +1059,18 @@
+
+ patch.avmStoreAsIdentifier
+ patch.avmStoreAsIdentifier.description
+ 0
+ 109
+ 110
+
+
+
+
+
+
+
+
diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties
index f4856caa1e..f2aa5f3460 100644
--- a/config/alfresco/version.properties
+++ b/config/alfresco/version.properties
@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number
-version.schema=109
+version.schema=110
diff --git a/source/java/org/alfresco/repo/admin/patch/impl/AVMStorePropertyTokenisationPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/AVMStorePropertyTokenisationPatch.java
new file mode 100644
index 0000000000..53c5cc473a
--- /dev/null
+++ b/source/java/org/alfresco/repo/admin/patch/impl/AVMStorePropertyTokenisationPatch.java
@@ -0,0 +1,99 @@
+/*
+ * 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 org.alfresco.i18n.I18NUtil;
+import org.alfresco.repo.admin.patch.AbstractPatch;
+import org.alfresco.repo.importer.ImporterBootstrap;
+import org.alfresco.repo.search.Indexer;
+import org.alfresco.repo.search.IndexerAndSearcher;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.cmr.search.ResultSet;
+import org.alfresco.service.cmr.search.ResultSetRow;
+import org.alfresco.service.cmr.search.SearchParameters;
+import org.alfresco.service.cmr.search.SearchService;
+
+/**
+ * Patch wca:webfolder objects so that the avmstore property is in the
+ * index in untokenized form.
+ *
+ * @author gavinc
+ *
+ */
+public class AVMStorePropertyTokenisationPatch extends AbstractPatch
+{
+ private static final String MSG_SUCCESS = "patch.avmStoreAsIdentifier.result";
+
+ private ImporterBootstrap spacesImporterBootstrap;
+ private IndexerAndSearcher indexerAndSearcher;
+
+ public AVMStorePropertyTokenisationPatch()
+ {
+
+ }
+
+ public void setSpacesImporterBootstrap(ImporterBootstrap spacesImporterBootstrap)
+ {
+ this.spacesImporterBootstrap = spacesImporterBootstrap;
+ }
+
+ public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher)
+ {
+ this.indexerAndSearcher = indexerAndSearcher;
+ }
+
+ @Override
+ protected String applyInternal() throws Exception
+ {
+ reindex("TYPE:\"wca:webfolder\"", spacesImporterBootstrap.getStoreRef());
+ return I18NUtil.getMessage(MSG_SUCCESS);
+ }
+
+ private void reindex(String query, StoreRef store)
+ {
+ SearchParameters sp = new SearchParameters();
+ sp.setLanguage(SearchService.LANGUAGE_LUCENE);
+ sp.setQuery(query);
+ sp.addStore(store);
+ ResultSet rs = null;
+ try
+ {
+ rs = searchService.query(sp);
+ for(ResultSetRow row : rs)
+ {
+ Indexer indexer = indexerAndSearcher.getIndexer(row.getNodeRef().getStoreRef());
+ indexer.updateNode(row.getNodeRef());
+ }
+ }
+ finally
+ {
+ if(rs != null)
+ {
+ rs.close();
+ }
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java
index de022298da..397189cd85 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java
@@ -59,6 +59,7 @@ import org.alfresco.repo.node.BaseNodeServiceTest;
import org.alfresco.repo.search.MLAnalysisMode;
import org.alfresco.repo.search.QueryParameterDefImpl;
import org.alfresco.repo.search.QueryRegisterComponent;
+import org.alfresco.repo.search.impl.lucene.analysis.DateTimeAnalyser;
import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer;
import org.alfresco.repo.search.results.ChildAssocRefResultSet;
import org.alfresco.repo.search.results.DetachedResultSet;
@@ -70,6 +71,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentService;
@@ -196,6 +198,8 @@ public class ADMLuceneTest extends TestCase
private NamespaceDAOImpl namespaceDao;
+ private Date testDate;
+
/**
*
*/
@@ -287,8 +291,9 @@ public class ADMLuceneTest extends TestCase
testProperties.put(QName.createQName(TEST_NAMESPACE, "long-ista"), Long.valueOf(2));
testProperties.put(QName.createQName(TEST_NAMESPACE, "float-ista"), Float.valueOf(3.4f));
testProperties.put(QName.createQName(TEST_NAMESPACE, "double-ista"), Double.valueOf(5.6));
- testProperties.put(QName.createQName(TEST_NAMESPACE, "date-ista"), new Date());
- testProperties.put(QName.createQName(TEST_NAMESPACE, "datetime-ista"), new Date());
+ testDate = new Date(new Date().getTime() - 10000);
+ testProperties.put(QName.createQName(TEST_NAMESPACE, "date-ista"), testDate);
+ testProperties.put(QName.createQName(TEST_NAMESPACE, "datetime-ista"), testDate);
testProperties.put(QName.createQName(TEST_NAMESPACE, "boolean-ista"), Boolean.valueOf(true));
testProperties.put(QName.createQName(TEST_NAMESPACE, "qname-ista"), QName.createQName("{wibble}wobble"));
testProperties.put(QName.createQName(TEST_NAMESPACE, "category-ista"), new NodeRef(storeRef, "CategoryId"));
@@ -2475,6 +2480,13 @@ public class ADMLuceneTest extends TestCase
assertEquals(0, results.length());
results.close();
+ // Dates
+
+ PropertyDefinition propertyDef = dictionaryService.getProperty(QName.createQName(TEST_NAMESPACE, "datetime-ista"));
+ DataTypeDefinition dataType = propertyDef.getDataType();
+ String analyserClassName = dataType.getAnalyserClassName();
+ boolean usesDateTimeAnalyser = analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName());
+
Date date = new Date();
String sDate = CachingDateFormat.getDateFormat().format(date);
results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "\\@" + escapeQName(QName.createQName(TEST_NAMESPACE, "date-ista")) + ":\"" + sDate + "\"", null, null);
@@ -2482,9 +2494,18 @@ public class ADMLuceneTest extends TestCase
results.close();
results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "\\@" + escapeQName(QName.createQName(TEST_NAMESPACE, "datetime-ista")) + ":\"" + sDate + "\"", null, null);
+ assertEquals(usesDateTimeAnalyser ? 0 : 1 , results.length());
+ results.close();
+
+ sDate = CachingDateFormat.getDateFormat().format(testDate);
+ results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "\\@" + escapeQName(QName.createQName(TEST_NAMESPACE, "date-ista")) + ":\"" + sDate + "\"", null, null);
assertEquals(1, results.length());
results.close();
+ results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "\\@" + escapeQName(QName.createQName(TEST_NAMESPACE, "datetime-ista")) + ":\"" + sDate + "\"", null, null);
+ assertEquals(1, results.length());
+ results.close();
+
results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "\\@" + escapeQName(QName.createQName(TEST_NAMESPACE, "boolean-ista")) + ":\"true\"", null, null);
assertEquals(1, results.length());
results.close();
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/analysis/DateTimeAnalyser.java b/source/java/org/alfresco/repo/search/impl/lucene/analysis/DateTimeAnalyser.java
new file mode 100644
index 0000000000..75d83aec89
--- /dev/null
+++ b/source/java/org/alfresco/repo/search/impl/lucene/analysis/DateTimeAnalyser.java
@@ -0,0 +1,45 @@
+/*
+ * 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.search.impl.lucene.analysis;
+
+import java.io.Reader;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.TokenStream;
+
+public class DateTimeAnalyser extends Analyzer
+{
+
+ public DateTimeAnalyser()
+ {
+ super();
+ }
+
+ // Split at the T in the XML date form
+ public TokenStream tokenStream(String fieldName, Reader reader)
+ {
+ return new DateTimeTokenFilter(reader);
+ }
+}
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/analysis/DateTimeTokenFilter.java b/source/java/org/alfresco/repo/search/impl/lucene/analysis/DateTimeTokenFilter.java
new file mode 100644
index 0000000000..77ed11443c
--- /dev/null
+++ b/source/java/org/alfresco/repo/search/impl/lucene/analysis/DateTimeTokenFilter.java
@@ -0,0 +1,74 @@
+/*
+ * 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.search.impl.lucene.analysis;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.alfresco.util.CachingDateFormat;
+import org.apache.lucene.analysis.Token;
+import org.apache.lucene.analysis.Tokenizer;
+import org.apache.lucene.analysis.WhitespaceTokenizer;
+
+/**
+ * @author andyh
+ */
+public class DateTimeTokenFilter extends Tokenizer
+{
+ Tokenizer baseTokeniser;
+
+ public DateTimeTokenFilter(Reader in)
+ {
+ super(in);
+ baseTokeniser = new WhitespaceTokenizer(in);
+ }
+
+ public Token next() throws IOException
+ {
+ SimpleDateFormat df = CachingDateFormat.getDateFormat();
+ SimpleDateFormat dof = CachingDateFormat.getDateFormat();
+ Token candidate;
+ while((candidate = baseTokeniser.next()) != null)
+ {
+ Date date;
+ try
+ {
+ date = df.parse(candidate.termText());
+ }
+ catch (ParseException e)
+ {
+ continue;
+ }
+ String valueString = dof.format(date);
+ Token integerToken = new Token(valueString, candidate.startOffset(), candidate.startOffset(),
+ candidate.type());
+ return integerToken;
+ }
+ return null;
+ }
+}
\ No newline at end of file