diff --git a/config/alfresco/content-services-context.xml b/config/alfresco/content-services-context.xml
index e55048b7fd..ee35b6722f 100644
--- a/config/alfresco/content-services-context.xml
+++ b/config/alfresco/content-services-context.xml
@@ -672,6 +672,16 @@
+
+
+
+
@@ -712,6 +722,16 @@
+
+
+
+
diff --git a/config/alfresco/ibatis/org.hibernate.dialect.PostgreSQLDialect/alfresco-util-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.PostgreSQLDialect/alfresco-util-SqlMap.xml
new file mode 100644
index 0000000000..a6d9941859
--- /dev/null
+++ b/config/alfresco/ibatis/org.hibernate.dialect.PostgreSQLDialect/alfresco-util-SqlMap.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+ escape E'\\'
+
+
+
\ No newline at end of file
diff --git a/config/alfresco/messages/action-config_it.properties b/config/alfresco/messages/action-config_it.properties
index 5ed6e26517..80cc71b6e3 100755
--- a/config/alfresco/messages/action-config_it.properties
+++ b/config/alfresco/messages/action-config_it.properties
@@ -176,6 +176,10 @@ start-workflow.workflowName.display-label=Nome workflow
start-workflow.endStartTask.display-label=Compito
start-workflow.startTaskTransition.display-label=Transizione
+cancel-workflow.title=Cancella i workflow
+cancel-workflow.description=Cancella la lista dei workflow con un determinato ID
+cancel-workflow.workflow-id-list.display-label=Lista di workflow con ID
+
#WCM Actions
simple-avm-submit.title=Invio diretto semplice
diff --git a/config/alfresco/messages/bpm-messages_it.properties b/config/alfresco/messages/bpm-messages_it.properties
index bf53341b63..9d39950619 100755
--- a/config/alfresco/messages/bpm-messages_it.properties
+++ b/config/alfresco/messages/bpm-messages_it.properties
@@ -57,9 +57,8 @@ bpm_businessprocessmodel.aspect.bpm_workflowPackage.description=Raccolta di cont
bpm_businessprocessmodel.type.bpm_activitiStartTask.title=Inizia il compito del workflow
bpm_businessprocessmodel.type.bpm_activitiStartTask.description=Compito per raccogliere le informazioni necessarie per iniziare il workflow
-#Workflow Start Task
bpm_businessprocessmodel.type.bpm_startTask.title=Compito di avvio del workflow
-bpm_businessprocessmodel.type.bpm_startTask.description=Compito utilizzato per raccogliere le informazioni richieste per l'avvio del workflow
+bpm_businessprocessmodel.type.bpm_startTask.description=Compito per raccogliere le informazioni necessarie per iniziare il workflow
bpm_businessprocessmodel.property.bpm_workflowDescription.title=Descrizione
bpm_businessprocessmodel.property.bpm_workflowDescription.description=Descrizione
bpm_businessprocessmodel.property.bpm_workflowDueDate.title=Data di scadenza del workflow
diff --git a/config/alfresco/messages/categories_it.properties b/config/alfresco/messages/categories_it.properties
new file mode 100755
index 0000000000..1343d0c056
--- /dev/null
+++ b/config/alfresco/messages/categories_it.properties
@@ -0,0 +1,6 @@
+message.changeCategoryName.success=Il nome della categoria \u00e8 stato cambiato con successo
+message.changeCategoryName.solr.success=L'aggiornamento della categoria \u00e8 stato inserito con successo nella coda di SOLR Il processo di aggiornamento potrebbe tardare alcuni minuti; per favore aggiornare la pagina per vedere la modifica eseguita.
+message.addCategory.success=Categoria aggiunta con successo
+message.addCategory.solr.success=La nuova categoria \u00e8 stata inserita con successo nella coda di SOLR Il processo di aggiornamento potrebbe tardare alcuni minuti; per favore aggiornare la pagina per vedere la modifica eseguita.
+message.removeCategory.success=Categoria rimossa con successo
+message.removeCategory.solr.success=Eliminazione della categoria inserita con successo nella coda di SOLR Il processo di aggiornamento potrebbe tardare alcuni minuti; per favore aggiornare la pagina per vedere la modifica eseguita.
\ No newline at end of file
diff --git a/config/alfresco/messages/imap-service_it.properties b/config/alfresco/messages/imap-service_it.properties
index 135254f4bd..52298ea100 100755
--- a/config/alfresco/messages/imap-service_it.properties
+++ b/config/alfresco/messages/imap-service_it.properties
@@ -11,4 +11,4 @@ imap.server.error.permission_denied = "Impossibile creare la cartella - Permesso
imap.server.error.folder_already_exist = "La cartella esiste gi\u00e0."
imap.server.error.mailbox_name_is_mandatory = "Il nome della cassetta postale \u00e8 un parametro obbligatorio."
imap.server.error.cannot_get_a_folder = "Impossibile recuperare una cartella con il nome ''{0}''."
-imap.server.error.cannot_parse_default_email = "Impossibile analizzare l'indirizzo e-mail predefinito address ''{0}''."
+imap.server.error.cannot_parse_default_email = "Impossibile analizzare l'indirizzo e-mail predefinito ''{0}''."
diff --git a/config/alfresco/messages/lock-service_it.properties b/config/alfresco/messages/lock-service_it.properties
index c4192b9131..718562c900 100755
--- a/config/alfresco/messages/lock-service_it.properties
+++ b/config/alfresco/messages/lock-service_it.properties
@@ -1,6 +1,6 @@
# Lock service externalised display strings
-lock_service.insufficent_privileges=Privilegi insufficienti per rilasciare il blocco del nodo (id: {0}). Il nodo \u00e8 bloccato da un altro utente.
+lock_service.insufficent_privileges=Privilegi insufficienti per rilasciare il blocco del nodo (id: {0}). Il nodo \u00e8 bloccato da un altro utente.
lock_service.node_locked=Impossibile bloccare il nodo (id: {0}) perch\u00e9 \u00e8 gi\u00e0 bloccato da un altro utente.
lock_service.no_op=Impossibile eseguire l''operazione perch\u00e9 il nodo (id: {0}) \u00e8 bloccato.
lock_service.no_op2=Impossibile eseguire l''operazione {0} perch\u00e9 il nodo (id: {1}) \u00e8 bloccato.
diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index e47f591ff3..f3dfa382ad 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -152,6 +152,7 @@ patch.siteLoadPatch.description=Loads a sample site into the repository.
patch.siteLoadPatch.exists=The Site {0} already exists and so could not be imported
patch.siteLoadPatch.noBootstrapViews=No bootstrap views were given for importing Site {0} - please check the bootstrap extension bean configuration
patch.siteLoadPatch.result=Site {0} imported.
+patch.siteLoadPatch.siteNotCreated=The site {0} is only created for new installs.
patch.wcmFolders.description=Ensures the existance of the WCM specific 'Web Projects' and 'Web Forms' folders.
patch.wcmFolders.webprojects.result.exists=The Web Projects folder already exists: {0}
diff --git a/config/alfresco/messages/patch-service_it.properties b/config/alfresco/messages/patch-service_it.properties
index 20da4afe54..e367a84b2f 100755
--- a/config/alfresco/messages/patch-service_it.properties
+++ b/config/alfresco/messages/patch-service_it.properties
@@ -453,3 +453,5 @@ patch.fixBpmPackages.description=Corrects workflow package types and association
patch.fixBpmPackages.result=Patch successful. {0} packages converted.
patch.fixBpmPackages.invalidBootsrapStore=Bootstrap store has not been set
patch.fixBpmPackages.emptyContainer={0} node has no children
+
+patch.alterJBPM331CLOBcolumnsToNvarchar.description=Altering CLOB columns in the jBPM 3.3.1 tables to introduce Unicode characters support for jBPM 3.3.1
diff --git a/config/alfresco/messages/system-messages_it.properties b/config/alfresco/messages/system-messages_it.properties
index f507ad5fe8..50de8bd201 100755
--- a/config/alfresco/messages/system-messages_it.properties
+++ b/config/alfresco/messages/system-messages_it.properties
@@ -32,6 +32,7 @@ system.schema_comp.redundant_obj.many_matches={0} redundant items? reference: {1
system.schema_comp.validation=Validation: {0} {1}="{2}" fails to match rule: {3}
# Specific validator (implementations) messages...
system.schema_comp.name_validator=name must match pattern ''{0}''
+system.schema_comp.schema_version_validator=version must be at least ''{0}''
# OpenOffice
system.openoffice.info.connection_verified=The connection to OpenOffice has been established.
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index 8cb49e34f4..42a9a181c3 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -2562,6 +2562,7 @@
+
diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties
index d35078c2c8..e5920d77ab 100644
--- a/config/alfresco/repository.properties
+++ b/config/alfresco/repository.properties
@@ -608,9 +608,11 @@ content.transformer.complex.Text.Pdf2swf.maxSourceSizeKBytes=1024
# Has implication for Share preview which generally goes via pdf to get to swf
content.transformer.OpenOffice.mimeTypeLimits.txt.pdf.maxSourceSizeKBytes=1024
content.transformer.OpenOffice.mimeTypeLimits.xlsx.pdf.maxSourceSizeKBytes=1024
+content.transformer.OpenOffice.mimeTypeLimits.xls.pdf.maxSourceSizeKBytes=1024
content.transformer.JodConverter.mimeTypeLimits.txt.pdf.maxSourceSizeKBytes=1024
content.transformer.JodConverter.mimeTypeLimits.xlsx.pdf.maxSourceSizeKBytes=1024
+content.transformer.JodConverter.mimeTypeLimits.xls.pdf.maxSourceSizeKBytes=1024
# Property to enable upgrade from 2.1-A
V2.1-A.fixes.to.schema=0
diff --git a/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java b/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java
index bb0d74e72e..a09ebe2db2 100644
--- a/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java
+++ b/source/java/org/alfresco/filesys/repo/ContentDiskDriver2.java
@@ -2421,7 +2421,7 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
if(fileInfo.isDirectory())
{
logger.debug("open file - is a directory!");
- netFile = new AlfrescoFolder(path, fileInfo, readOnly);
+ netFile = new AlfrescoFolder(path, fileInfo, readOnly);
}
else
{
@@ -2459,14 +2459,6 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
netFile.truncateFile(0);
}
- // Generate a file id for the file
-
- if ( netFile != null)
- {
- long id = DefaultTypeConverter.INSTANCE.convert(Long.class, nodeService.getProperty(nodeRef, ContentModel.PROP_NODE_DBID));
- netFile.setFileId((int) (id & 0xFFFFFFFFL));
- }
-
if (logger.isDebugEnabled())
{
logger.debug("Created file: path=" + name + " node=" + nodeRef + " network file=" + netFile);
@@ -2499,14 +2491,6 @@ public class ContentDiskDriver2 extends AlfrescoDiskDriver implements ExtendedD
// Needs to be READWRITE for JavaNetworkFile - there's no such thing as WRITEONLY!
netFile.setGrantedAccess( NetworkFile.READWRITE);
- // Generate a file id for the file
-
- if ( netFile != null)
- {
- long id = DefaultTypeConverter.INSTANCE.convert(Long.class, nodeService.getProperty(nodeRef, ContentModel.PROP_NODE_DBID));
- netFile.setFileId((int) (id & 0xFFFFFFFFL));
- }
-
if (logger.isDebugEnabled())
{
logger.debug("Created temporary file: path=" + name + " node=" + nodeRef + " network file=" + netFile);
diff --git a/source/java/org/alfresco/filesys/repo/LegacyFileStateDriver.java b/source/java/org/alfresco/filesys/repo/LegacyFileStateDriver.java
index 6614ba731c..44c5831f54 100644
--- a/source/java/org/alfresco/filesys/repo/LegacyFileStateDriver.java
+++ b/source/java/org/alfresco/filesys/repo/LegacyFileStateDriver.java
@@ -37,6 +37,7 @@ import org.alfresco.jlan.server.filesys.TreeConnection;
import org.alfresco.jlan.server.filesys.cache.FileState;
import org.alfresco.jlan.server.filesys.cache.FileStateCache;
import org.alfresco.jlan.server.filesys.cache.NetworkFileStateInterface;
+import org.alfresco.jlan.server.filesys.pseudo.PseudoFile;
import org.alfresco.jlan.smb.SharingMode;
import org.alfresco.model.ContentModel;
import org.alfresco.util.PropertyCheck;
@@ -99,6 +100,8 @@ public class LegacyFileStateDriver implements ExtendedDiskInterface
try
{
NetworkFile newFile = diskInterface.createFile(sess, tree, params);
+
+ newFile.setAccessToken(token);
if(tctx.hasStateCache())
{
@@ -194,68 +197,64 @@ public class LegacyFileStateDriver implements ExtendedDiskInterface
try
{
NetworkFile openFile = diskInterface.openFile(sess, tree, params);
-
+
+ openFile.setAccessToken(token);
+
+ FileState fstate = null;
+
+ if(tctx.hasStateCache())
+ {
+ fstate = tctx.getStateCache().findFileState( path, true);
+ fstate.setProcessId(params.getProcessId());
+ fstate.setSharedAccess( params.getSharedAccess());
+
+ // Access date time is read/write time not open time
+ // fstate.updateAccessDateTime();
+
+ fstate.setFileSize(openFile.getFileSize());
+ fstate.updateChangeDateTime(openFile.getModifyDate());
+ fstate.updateModifyDateTime(openFile.getModifyDate());
+ }
+
if (openFile instanceof ContentNetworkFile)
{
ContentNetworkFile x = (ContentNetworkFile)openFile;
x.setProcessId( params.getProcessId());
- x.setAccessToken(token);
- if(tctx.hasStateCache())
- {
- FileState fstate = tctx.getStateCache().findFileState( path, true);
- x.setFileState(fstate);
- fstate.setProcessId(params.getProcessId());
- fstate.setSharedAccess( params.getSharedAccess());
- fstate.setFileStatus(FileStatus.FileExists);
- // Access date time is read/write time not open time
- // fstate.updateAccessDateTime();
-
- fstate.setFileSize(x.getFileSize());
- fstate.updateChangeDateTime(x.getModifyDate());
- fstate.updateModifyDateTime(x.getModifyDate());
- }
- }
- if (openFile instanceof TempNetworkFile)
+ if(fstate != null)
+ {
+ x.setFileState(fstate);
+ fstate.setFileStatus(FileStatus.FileExists);
+ }
+ }
+ else if (openFile instanceof TempNetworkFile)
{
TempNetworkFile x = (TempNetworkFile)openFile;
- x.setAccessToken(token);
- // x.setProcessId( params.getProcessId());
- if(tctx.hasStateCache())
+ if(fstate != null)
{
- FileState fstate = tctx.getStateCache().findFileState( path, true);
x.setFileState(fstate);
fstate.setFileStatus(FileStatus.FileExists);
- fstate.setProcessId(params.getProcessId());
- fstate.setSharedAccess( params.getSharedAccess());
- // access date time is read/write time not open time
- //fstate.updateAccessDateTime();
-
- fstate.setFileSize(x.getFileSize());
- fstate.updateChangeDateTime(x.getModifyDate());
- fstate.updateModifyDateTime(x.getModifyDate());
}
}
-
- if (openFile instanceof AlfrescoFolder)
+ else if (openFile instanceof AlfrescoFolder)
{
AlfrescoFolder x = (AlfrescoFolder)openFile;
- //x.setProcessId( param.getProcessId());
- if(tctx.hasStateCache())
+ if(fstate != null)
{
- FileState fstate = tctx.getStateCache().findFileState( path, true);
x.setFileState(fstate);
fstate.setFileStatus(FileStatus.DirectoryExists);
- fstate.setProcessId(params.getProcessId());
- fstate.setSharedAccess( params.getSharedAccess());
- // Access date time is read/write time not open time
- //fstate.updateAccessDateTime();
-
- fstate.setFileSize(x.getFileSize());
- fstate.updateChangeDateTime(x.getModifyDate());
- fstate.updateModifyDateTime(x.getModifyDate());
}
}
+ else if (openFile instanceof NetworkFile)
+ {
+ NetworkFile x = (NetworkFile)openFile;
+ if(fstate != null)
+ {
+ // NetworkFile does not have setFileState
+ //x.setFileState(fstate);
+ fstate.setFileStatus(FileStatus.FileExists);
+ }
+ }
return openFile;
}
diff --git a/source/java/org/alfresco/repo/admin/patch/impl/SiteLoadPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/SiteLoadPatch.java
index 10bee9abb8..abb96b293a 100644
--- a/source/java/org/alfresco/repo/admin/patch/impl/SiteLoadPatch.java
+++ b/source/java/org/alfresco/repo/admin/patch/impl/SiteLoadPatch.java
@@ -41,6 +41,8 @@ import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.site.SiteVisibility;
import org.alfresco.service.cmr.view.ImporterBinding.UUID_BINDING;
+import org.alfresco.service.descriptor.Descriptor;
+import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -70,6 +72,7 @@ public class SiteLoadPatch extends AbstractPatch
private static final String MSG_SITE_ALREADY_EXISTS = "patch.siteLoadPatch.exists";
private static final String MSG_NO_BOOTSTRAP_VIEWS_GIVEN = "patch.siteLoadPatch.noBootstrapViews";
private static final String MSG_SITE_CREATED = "patch.siteLoadPatch.result";
+ private static final String MSG_SITE_NOT_CREATED = "patch.siteLoadPatch.siteNotCreated";
// Logger
private static final Log logger = LogFactory.getLog(SiteLoadPatch.class);
@@ -77,6 +80,7 @@ public class SiteLoadPatch extends AbstractPatch
private AuthorityService authorityService;
private BehaviourFilter behaviourFilter;
private SiteService siteService;
+ private DescriptorService descriptorService;
private String siteName;
@@ -117,7 +121,7 @@ public class SiteLoadPatch extends AbstractPatch
{
this.bootstrapViews = bootstrapViews;
}
-
+
/**
* Sets the Site Service to be used for importing into
*
@@ -138,6 +142,16 @@ public class SiteLoadPatch extends AbstractPatch
this.authorityService = authorityService;
}
+
+
+ /**
+ * @param descriptorService the descriptorService to set
+ */
+ public void setDescriptorService(DescriptorService descriptorService)
+ {
+ this.descriptorService = descriptorService;
+ }
+
public void setBehaviourFilter(BehaviourFilter behaviourFilter)
{
this.behaviourFilter = behaviourFilter;
@@ -177,6 +191,17 @@ public class SiteLoadPatch extends AbstractPatch
*/
private String applyInternalImpl() throws Exception
{
+ if(descriptorService != null)
+ {
+ // if the descriptor service is wired up only load the site at install time (and not on upgrade)
+ Descriptor installed = descriptorService.getInstalledRepositoryDescriptor();
+ Descriptor live = descriptorService.getServerDescriptor();
+
+ if(!installed.getVersion().equals(live.getVersion()))
+ {
+ return I18NUtil.getMessage(MSG_SITE_NOT_CREATED, siteName);
+ }
+ }
if (bootstrapViews == null || bootstrapViews.size() == 0)
{
if (logger.isDebugEnabled())
diff --git a/source/java/org/alfresco/repo/calendar/CalendarHelpersTest.java b/source/java/org/alfresco/repo/calendar/CalendarHelpersTest.java
index ecaae5b8e9..3d899c27a3 100644
--- a/source/java/org/alfresco/repo/calendar/CalendarHelpersTest.java
+++ b/source/java/org/alfresco/repo/calendar/CalendarHelpersTest.java
@@ -782,6 +782,314 @@ public class CalendarHelpersTest
assertEquals("2011-10-21", dateFmt.format(dates.get(1)));
assertEquals("2012-01-20", dateFmt.format(dates.get(2)));
}
+
+ /**
+ * eg every 21st of February
+ */
+ @Test public void yearlyRecurrenceByDateInMonth()
+ {
+ List dates = new ArrayList();
+ Calendar currentDate = Calendar.getInstance();
+
+ // How Outlook ought to do it
+ Map params = new HashMap();
+ params.put("COUNT", "10");
+ params.put("BYMONTH", "2");
+ params.put("BYMONTHDAY", "21");
+
+ // How many Outlook versions do do it...
+ // FREQ=MONTHLY;COUNT=10;BYMONTH=2;INTERVAL=1;BYSETPOS=17;BYDAY=SU,MO,TU,WE,TH,FR,SA;
+ Map paramsOUTLOOK = new HashMap();
+ paramsOUTLOOK.put("FREQ", "MONTHLY");
+ paramsOUTLOOK.put("COUNT", "10");
+ paramsOUTLOOK.put("BYMONTH", "2");
+ paramsOUTLOOK.put("INTERVAL", "1");
+ paramsOUTLOOK.put("BYSETPOS", "21");
+ paramsOUTLOOK.put("BYDAY", "SU,MO,TU,WE,TH,FR,SA");
+
+ // Check that the outlook crazy version gets fixed
+ Map paramsFIXED = RecurrenceHelper.fixOutlookRecurrenceQuirks(paramsOUTLOOK);
+ assertEquals("YEARLY", paramsFIXED.get("FREQ"));
+ assertEquals("2", paramsFIXED.get("BYMONTH"));
+ assertEquals("21", paramsFIXED.get("BYMONTHDAY"));
+ assertEquals("10", paramsFIXED.get("COUNT"));
+ assertEquals("1", paramsFIXED.get("INTERVAL"));
+ assertEquals(null, paramsFIXED.get("BYDAY"));
+ assertEquals(null, paramsFIXED.get("BYSETPOS"));
+
+
+ // Dates in the past, get nothing
+ dates.clear();
+ currentDate.set(2012,1-1,19,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,10), date(2012,2,15),
+ true, 1);
+ assertEquals(0, dates.size());
+
+ dates.clear();
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,10), date(2012,2,15),
+ false, 1);
+ assertEquals(0, dates.size());
+
+
+ // With the month that contains it
+ dates.clear();
+ currentDate.set(2012,2-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,1), date(2012,2,26),
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2012-02-21", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2012,2-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,1), date(2012,2,26),
+ false, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2012-02-21", dateFmt.format(dates.get(0)));
+
+
+ // In the next month
+ dates.clear();
+ currentDate.set(2012,3-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,3,1), date(2012,3,26),
+ true, 1);
+ assertEquals(0, dates.size());
+
+ dates.clear();
+ currentDate.set(2012,3-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,3,1), date(2012,3,26),
+ false, 1);
+ assertEquals(0, dates.size());
+
+
+ // From before, into the next year
+ dates.clear();
+ currentDate.set(2012,2-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,1), date(2013,3,26),
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2012-02-21", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2012,2-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,1), date(2013,3,26),
+ false, 1);
+ assertEquals(2, dates.size());
+ assertEquals("2012-02-21", dateFmt.format(dates.get(0)));
+ assertEquals("2013-02-21", dateFmt.format(dates.get(1)));
+
+
+ // From next month, into the next year
+ dates.clear();
+ currentDate.set(2012,3-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,3,1), date(2013,2,26),
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2013-02-21", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2012,3-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,3,1), date(2013,3,26),
+ false, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2013-02-21", dateFmt.format(dates.get(0)));
+
+
+ // With no end date but only first, check it behaves
+ dates.clear();
+ currentDate.set(2011,7-1,2,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2011,7,1), null,
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2012-02-21", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2012,7-1,19,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2011,7,19), null,
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2013-02-21", dateFmt.format(dates.get(0)));
+ }
+
+ /**
+ * eg the 2nd Thursday in every March
+ */
+ @Test public void yearlyRecurrenceByDayOfWeekInMonth()
+ {
+ List dates = new ArrayList();
+ Calendar currentDate = Calendar.getInstance();
+
+ // How Outlook ought to do it
+ Map params = new HashMap();
+ params.put("COUNT", "7");
+ params.put("BYMONTH", "2");
+ params.put("BYDAY", "SA");
+ params.put("BYSETPOS", "2");
+
+ // 2nd Saturday in February is 11th Feb 2012, 9th Feb 2013
+
+ // Note - outlook seems to like to set these as monthly...
+ // FREQ=MONTHLY;COUNT=7;BYDAY=SA;BYMONTH=2;BYSETPOS=2;INTERVAL=1
+ // This is right except for the FREQ!
+ Map paramsOUTLOOK = new HashMap();
+ paramsOUTLOOK.put("FREQ", "MONTHLY");
+ paramsOUTLOOK.put("COUNT", "7");
+ paramsOUTLOOK.put("BYMONTH", "2");
+ paramsOUTLOOK.put("BYDAY", "SA");
+ paramsOUTLOOK.put("BYSETPOS", "2");
+ paramsOUTLOOK.put("INTERVAL", "1");
+
+ // Check that the outlook crazy version gets fixed
+ Map paramsFIXED = RecurrenceHelper.fixOutlookRecurrenceQuirks(paramsOUTLOOK);
+ assertEquals("YEARLY", paramsFIXED.get("FREQ"));
+ assertEquals("2", paramsFIXED.get("BYMONTH"));
+ assertEquals("SA", paramsFIXED.get("BYDAY"));
+ assertEquals("2", paramsFIXED.get("BYSETPOS"));
+ assertEquals("7", paramsFIXED.get("COUNT"));
+ assertEquals("1", paramsFIXED.get("INTERVAL"));
+ assertEquals(null, paramsFIXED.get("BYMONTHDAY"));
+
+
+
+
+ // Dates in the past, get nothing
+ dates.clear();
+ currentDate.set(2012,1-1,19,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,4), date(2012,2,5),
+ true, 1);
+ assertEquals(0, dates.size());
+
+ dates.clear();
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,4), date(2012,2,5),
+ false, 1);
+ assertEquals(0, dates.size());
+
+
+ // With the month that contains it
+ dates.clear();
+ currentDate.set(2012,2-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,1), date(2012,2,26),
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2012-02-11", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2012,2-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,1), date(2012,2,26),
+ false, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2012-02-11", dateFmt.format(dates.get(0)));
+
+
+ // In the next month
+ dates.clear();
+ currentDate.set(2012,3-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,3,1), date(2012,3,26),
+ true, 1);
+ assertEquals(0, dates.size());
+
+ dates.clear();
+ currentDate.set(2012,3-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,3,1), date(2012,3,26),
+ false, 1);
+ assertEquals(0, dates.size());
+
+
+ // From before, into the next year
+ dates.clear();
+ currentDate.set(2012,2-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,1), date(2013,3,26),
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2012-02-11", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2012,2-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,2,1), date(2013,3,26),
+ false, 1);
+ assertEquals(2, dates.size());
+ assertEquals("2012-02-11", dateFmt.format(dates.get(0)));
+ assertEquals("2013-02-09", dateFmt.format(dates.get(1)));
+
+
+ // From next month, into the next year
+ dates.clear();
+ currentDate.set(2012,3-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,3,1), date(2013,2,26),
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2013-02-09", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2012,3-1,1,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2012,3,1), date(2013,3,26),
+ false, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2013-02-09", dateFmt.format(dates.get(0)));
+
+
+ // With no end date but only first, check it behaves
+ dates.clear();
+ currentDate.set(2011,7-1,2,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2011,7,1), null,
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2012-02-11", dateFmt.format(dates.get(0)));
+
+ dates.clear();
+ currentDate.set(2012,7-1,19,10,30);
+ RecurrenceHelper.buildYearlyRecurrences(
+ currentDate, dates, params,
+ date(2011,7,19), null,
+ true, 1);
+ assertEquals(1, dates.size());
+ assertEquals("2013-02-09", dateFmt.format(dates.get(0)));
+ }
/**
* Checks we correctly build the Timezone for somewhere
@@ -921,6 +1229,11 @@ public class CalendarHelpersTest
CalendarRecurrenceHelper.buildYearlyRecurrences(
currentDate, dates, params, onOrAfter, until, firstOnly, interval);
}
+
+ protected static Map fixOutlookRecurrenceQuirks(Map params)
+ {
+ return CalendarRecurrenceHelper.fixOutlookRecurrenceQuirks(params);
+ }
}
private static Date date(int year, int month, int day)
diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
index 647ed5d4c6..535fa643ca 100644
--- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
+++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
@@ -2552,6 +2552,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
Pair newChildNodePair = moveResult.getSecond();
ChildAssociationRef newParentAssocRef = newParentAssocPair.getSecond();
// Index
+ nodeIndexer.indexDeleteNode(oldParentAssocPair.getSecond());
nodeIndexer.indexCreateNode(newParentAssocPair.getSecond());
// Propagate timestamps
propagateTimeStamps(oldParentAssocRef);
diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrChildApplicationContextFactory.java b/source/java/org/alfresco/repo/search/impl/solr/SolrChildApplicationContextFactory.java
index 9e354d9801..5f8978759d 100644
--- a/source/java/org/alfresco/repo/search/impl/solr/SolrChildApplicationContextFactory.java
+++ b/source/java/org/alfresco/repo/search/impl/solr/SolrChildApplicationContextFactory.java
@@ -63,9 +63,7 @@ public class SolrChildApplicationContextFactory extends ChildApplicationContextF
@Override
public String getProperty(String name)
{
- if (name.equals(SolrChildApplicationContextFactory.ALFRESCO_ACTIVE)
- || name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG) || name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG_DURATION) || name.equals(SolrChildApplicationContextFactory.ARCHIVE_ACTIVE)
- || name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG) || name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG_DURATION))
+ if (false == isUpdateable(name))
{
try
{
@@ -150,50 +148,10 @@ public class SolrChildApplicationContextFactory extends ChildApplicationContextF
public void setProperty(String name, String value)
{
- if (name.equals(SolrChildApplicationContextFactory.ALFRESCO_ACTIVE)
- || name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG) || name.equals(SolrChildApplicationContextFactory.ALFRESCO_LAG_DURATION) || name.equals(SolrChildApplicationContextFactory.ARCHIVE_ACTIVE)
- || name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG) || name.equals(SolrChildApplicationContextFactory.ARCHIVE_LAG_DURATION))
+ if(false == isUpdateable(name))
{
throw new IllegalStateException("Illegal write to property \"" + name + "\"");
}
super.setProperty(name, value);
- }
-
- /* (non-Javadoc)
- * @see org.alfresco.repo.management.subsystems.AbstractPropertyBackedBean#setProperties(java.util.Map)
- */
- @Override
- public void setProperties(Map properties)
- {
- // Remove any read only properties
- HashMap propertiesToSet = new HashMap(properties);
- if(propertiesToSet.containsKey(SolrChildApplicationContextFactory.ALFRESCO_ACTIVE))
- {
- propertiesToSet.remove(SolrChildApplicationContextFactory.ALFRESCO_ACTIVE);
- }
- if(propertiesToSet.containsKey(SolrChildApplicationContextFactory.ALFRESCO_LAG))
- {
- propertiesToSet.remove(SolrChildApplicationContextFactory.ALFRESCO_LAG);
- }
- if(propertiesToSet.containsKey(SolrChildApplicationContextFactory.ALFRESCO_LAG_DURATION))
- {
- propertiesToSet.remove(SolrChildApplicationContextFactory.ALFRESCO_LAG_DURATION);
- }
- if(propertiesToSet.containsKey(SolrChildApplicationContextFactory.ARCHIVE_ACTIVE))
- {
- propertiesToSet.remove(SolrChildApplicationContextFactory.ARCHIVE_ACTIVE);
- }
- if(propertiesToSet.containsKey(SolrChildApplicationContextFactory.ARCHIVE_LAG))
- {
- propertiesToSet.remove(SolrChildApplicationContextFactory.ARCHIVE_LAG);
- }
- if(propertiesToSet.containsKey(SolrChildApplicationContextFactory.ARCHIVE_LAG_DURATION))
- {
- propertiesToSet.remove(SolrChildApplicationContextFactory.ARCHIVE_LAG_DURATION);
- }
-
- super.setProperties(propertiesToSet);
- }
-
-
+ }
}
diff --git a/source/java/org/alfresco/service/cmr/calendar/CalendarRecurrenceHelper.java b/source/java/org/alfresco/service/cmr/calendar/CalendarRecurrenceHelper.java
index e226dbe58b..ded5b92690 100644
--- a/source/java/org/alfresco/service/cmr/calendar/CalendarRecurrenceHelper.java
+++ b/source/java/org/alfresco/service/cmr/calendar/CalendarRecurrenceHelper.java
@@ -122,6 +122,43 @@ public class CalendarRecurrenceHelper
return params;
}
+ /**
+ * Outlook does some crazy stuff, which is only just about permitted by
+ * the specification, and is hard to parse, especially for yearly events.
+ * Fix these to more normal cases where possible
+ */
+ protected static Map fixOutlookRecurrenceQuirks(Map params)
+ {
+ if (params.containsKey("FREQ"))
+ {
+ // Is it really yearly?
+ if ("MONTHLY".equals(params.get("FREQ")) &&
+ params.get("BYMONTH") != null)
+ {
+ // Outlook can be "delightfully" different, and likes to generate
+ // events that recur yearly on a specific date+month as FREQ=MONTHLY
+ // Detect those cases, and treat as YEARLY as per the spec
+ params.put("FREQ", "YEARLY");
+
+ // Outlook will sometimes do nth of the month (eg 17) instead as
+ // BYDAY={any}, BYSETPOS=n
+ if (params.containsKey("BYDAY") && params.containsKey("BYSETPOS"))
+ {
+ int days = params.get("BYDAY").split(",").length;
+ if (days == 7)
+ {
+ // Make it normal
+ params.put("BYMONTHDAY", params.get("BYSETPOS"));
+ params.remove("BYDAY");
+ params.remove("BYSETPOS");
+ }
+ }
+ }
+ }
+ return params;
+ }
+
+
/**
* For the given Calendar Entry, return its subsequent Recurrence on or after
* the specified date, until the given limit. If it doesn't have any recurrences
@@ -194,8 +231,15 @@ public class CalendarRecurrenceHelper
// To hold our events
List dates = new ArrayList();
- // Handle the different frequencies
+ // Extract out the rule into its parts
Map params = extractRecurrenceRule(recurrenceRule);
+
+ // Outlook does some crazy stuff, which is only just about
+ // permitted by the specification, and is hard to parse
+ // Fix these to more normal cases where possible
+ params = fixOutlookRecurrenceQuirks(params);
+
+ // Fetch the frequency and interval
if (params.containsKey("FREQ"))
{
String freq = params.get("FREQ");
@@ -213,6 +257,7 @@ public class CalendarRecurrenceHelper
}
}
+ // Start with today, and roll forward
Calendar currentDate = Calendar.getInstance();
currentDate.setTime(eventStart);
@@ -458,7 +503,8 @@ public class CalendarRecurrenceHelper
protected static void buildYearlyRecurrences(Calendar currentDate, List dates,
Map params, Date onOrAfter, Date until, boolean firstOnly, int interval)
{
- int month = Integer.parseInt(params.get("BYMONTH"));
+ int realMonth = Integer.parseInt(params.get("BYMONTH"));
+ int month = realMonth - 1; // Java months count from zero
if (params.get("BYMONTHDAY") != null)
{
@@ -469,12 +515,22 @@ public class CalendarRecurrenceHelper
{
// Correct start time
}
- else
+ else if (currentDate.get(Calendar.MONTH) < month ||
+ (currentDate.get(Calendar.MONTH) == month &&
+ currentDate.get(Calendar.DAY_OF_MONTH) < dayOfMonth))
{
- currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + interval);
+ // The current date is before the requested date this year
+ // Move forward to it in this year
currentDate.set(Calendar.MONTH, month);
currentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
}
+ else
+ {
+ // The current date is after the date this year, move to next year
+ currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + interval);
+ currentDate.set(Calendar.MONTH, month);
+ currentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+ }
while (currentDate.getTime().before(onOrAfter))
{
@@ -505,10 +561,79 @@ public class CalendarRecurrenceHelper
}
else
{
- // eg the first Tuesday in February every year
- int dayOfWeek = DAY_NAMES_TO_CALENDAR_DAYS.get(params.get("BYSETPOS"));
- // TODO
- }
+ // eg the third Tuesday in February every year
+ int dayOfWeek = -1;
+ int instanceInMonth = 1;
+
+ // There are two forms...
+ if (params.containsKey("BYDAY"))
+ {
+ dayOfWeek = DAY_NAMES_TO_CALENDAR_DAYS.get(params.get("BYDAY"));
+ instanceInMonth = Integer.parseInt(params.get("BYSETPOS"));
+ }
+ else
+ {
+ // Implies the first one in the month
+ dayOfWeek = DAY_NAMES_TO_CALENDAR_DAYS.get(params.get("BYSETPOS"));
+ instanceInMonth = 1;
+ }
+
+
+ // Find when it is this year
+ Date origDate = currentDate.getTime();
+ currentDate.set(Calendar.MONTH, month);
+ currentDate.set(Calendar.DAY_OF_MONTH, 1);
+ toDayOfWeekInMonth(currentDate, dayOfWeek, instanceInMonth);
+ Date thisYear = currentDate.getTime();
+ currentDate.setTime(origDate);
+
+ // Have we missed it for the year? If so, go to next year
+ if (currentDate.getTime().after(thisYear))
+ {
+ currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + interval);
+ currentDate.set(Calendar.MONTH, month);
+ currentDate.set(Calendar.DAY_OF_MONTH, 1);
+ toDayOfWeekInMonth(currentDate, dayOfWeek, instanceInMonth);
+ }
+ else
+ {
+ // Otherwise move to it
+ currentDate.setTime(thisYear);
+ }
+
+
+ // Move forward to the required date
+ while (currentDate.getTime().before(onOrAfter))
+ {
+ currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + interval);
+ currentDate.set(Calendar.MONTH, month);
+ currentDate.set(Calendar.DAY_OF_MONTH, 1);
+ toDayOfWeekInMonth(currentDate, dayOfWeek, instanceInMonth);
+ }
+
+ // Roll on until we get valid matches
+ while (true)
+ {
+ if (until != null)
+ {
+ if (currentDate.getTime().after(until))
+ {
+ break;
+ }
+ }
+
+ dates.add(currentDate.getTime());
+ if (firstOnly)
+ {
+ break;
+ }
+
+ currentDate.set(Calendar.YEAR, currentDate.get(Calendar.YEAR) + interval);
+ currentDate.set(Calendar.MONTH, month);
+ currentDate.set(Calendar.DAY_OF_MONTH, 1);
+ toDayOfWeekInMonth(currentDate, dayOfWeek, instanceInMonth);
+ }
+ }
}
private static void addMonthToDayOfMonth(Calendar c, int dayOfMonth, int monthInterval)