diff --git a/config/alfresco/application-context.xml b/config/alfresco/application-context.xml index d8b605eedf..2f09ea5b40 100644 --- a/config/alfresco/application-context.xml +++ b/config/alfresco/application-context.xml @@ -52,6 +52,7 @@ + diff --git a/config/alfresco/model/dictionaryModel.xml b/config/alfresco/model/dictionaryModel.xml index 9bee7d365a..e870393d6c 100644 --- a/config/alfresco/model/dictionaryModel.xml +++ b/config/alfresco/model/dictionaryModel.xml @@ -112,6 +112,11 @@ org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser org.alfresco.util.VersionNumber + + + org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser + org.alfresco.service.cmr.repository.Period + diff --git a/source/java/org/alfresco/cmis/mapping/CMISMapping.java b/source/java/org/alfresco/cmis/mapping/CMISMapping.java index 79ea7b9ea4..cd099fe1de 100644 --- a/source/java/org/alfresco/cmis/mapping/CMISMapping.java +++ b/source/java/org/alfresco/cmis/mapping/CMISMapping.java @@ -156,6 +156,7 @@ public class CMISMapping implements InitializingBean mapAlfrescoToCmisDataType.put(DataTypeDefinition.FLOAT, CMISDataTypeEnum.DECIMAL); mapAlfrescoToCmisDataType.put(DataTypeDefinition.INT, CMISDataTypeEnum.INTEGER); mapAlfrescoToCmisDataType.put(DataTypeDefinition.LOCALE, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.PERIOD, null); mapAlfrescoToCmisDataType.put(DataTypeDefinition.LONG, CMISDataTypeEnum.INTEGER); mapAlfrescoToCmisDataType.put(DataTypeDefinition.MLTEXT, CMISDataTypeEnum.STRING); mapAlfrescoToCmisDataType.put(DataTypeDefinition.NODE_REF, CMISDataTypeEnum.ID); diff --git a/source/java/org/alfresco/repo/dictionary/types/period/AbstractCalendarPeriodProvider.java b/source/java/org/alfresco/repo/dictionary/types/period/AbstractCalendarPeriodProvider.java new file mode 100644 index 0000000000..93a89c78bb --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/AbstractCalendarPeriodProvider.java @@ -0,0 +1,67 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; +import java.util.Date; + +/** + * Support for calendar based periods + * @author andyh + * + */ +public abstract class AbstractCalendarPeriodProvider extends AbstractPeriodProvider +{ + + public String getDefaultExpression() + { + return "1"; + } + + public ExpressionMutiplicity getExpressionMutiplicity() + { + return ExpressionMutiplicity.OPTIONAL; + } + + public Date getNextDate(Date date, String expression) + { + int value = Integer.parseInt(expression); + + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + + add(calendar, value); + Date next = calendar.getTime(); + return next; + } + + /** + * Implementation add + * @param calendar + * @param value + */ + public abstract void add(Calendar calendar, int value); + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/AbstractEndOfCalendarPeriodProvider.java b/source/java/org/alfresco/repo/dictionary/types/period/AbstractEndOfCalendarPeriodProvider.java new file mode 100644 index 0000000000..e08790d463 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/AbstractEndOfCalendarPeriodProvider.java @@ -0,0 +1,75 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; + +/** + * Support for calendar based "end of" periods with month and day offsets for fiscal year support + * @author andyh + * + */ +public abstract class AbstractEndOfCalendarPeriodProvider extends AbstractCalendarPeriodProvider +{ + private int startDayOfMonth = 1; + + private int startMonth = Calendar.JANUARY; + + /** + * Get the start day of the month (as defined by Calendar) + * @return - the start day of the month + */ + public int getStartDayOfMonth() + { + return startDayOfMonth; + } + + /** + * Set the start day of the month (as defined by Calendar) + * @param startDayOfMonth + */ + public void setStartDayOfMonth(int startDayOfMonth) + { + this.startDayOfMonth = startDayOfMonth; + } + + /** + * Get the start month (as defined by Calendar) + * @return - the start month + */ + public int getStartMonth() + { + return startMonth; + } + + /** + * Set the start month (as defined by Calendar) + * @param startMonth + */ + public void setStartMonth(int startMonth) + { + this.startMonth = startMonth; + } +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/AbstractPeriodProvider.java b/source/java/org/alfresco/repo/dictionary/types/period/AbstractPeriodProvider.java new file mode 100644 index 0000000000..1444cb5683 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/AbstractPeriodProvider.java @@ -0,0 +1,53 @@ +/* + * 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.dictionary.types.period; + +import org.alfresco.service.cmr.repository.Period; +import org.alfresco.service.cmr.repository.PeriodProvider; +import org.springframework.beans.factory.InitializingBean; + +/** + * Common support for period implementations. + * + * They are Spring beans that register in the bootstrap context. + * + * @author andyh + * + */ +public abstract class AbstractPeriodProvider implements PeriodProvider, InitializingBean +{ + /** + * Default constructor + */ + public AbstractPeriodProvider() + { + super(); + } + + public void afterPropertiesSet() throws Exception + { + Period.registerProvider(this); + } +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/Cron.java b/source/java/org/alfresco/repo/dictionary/types/period/Cron.java new file mode 100644 index 0000000000..24544c3ea2 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/Cron.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.dictionary.types.period; + +import java.text.ParseException; +import java.util.Date; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.quartz.CronExpression; + +/** + * Cron based periods + * @author andyh + * + */ +public class Cron extends AbstractPeriodProvider +{ + /** + * Period type + */ + public static final String PERIOD_TYPE = "cron"; + + public String getDefaultExpression() + { + return "59 59 23 * * ?"; + } + + public ExpressionMutiplicity getExpressionMutiplicity() + { + return ExpressionMutiplicity.MANDATORY; + } + + public Date getNextDate(Date date, String expression) + { + CronExpression ce; + try + { + ce = new CronExpression(expression); + } + catch (ParseException e) + { + throw new AlfrescoRuntimeException("Invalid cron expression: "+expression); + } + return ce.getNextValidTimeAfter(date); + } + + public String getPeriodType() + { + return PERIOD_TYPE; + } + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/Days.java b/source/java/org/alfresco/repo/dictionary/types/period/Days.java new file mode 100644 index 0000000000..531059d07f --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/Days.java @@ -0,0 +1,53 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; + + +/** + * Day based periods + * @author andyh + * + */ +public class Days extends AbstractCalendarPeriodProvider +{ + /** + * + */ + public static final String PERIOD_TYPE = "day"; + + public String getPeriodType() + { + return PERIOD_TYPE; + } + + @Override + public void add(Calendar calendar, int value) + { + calendar.add(Calendar.DAY_OF_YEAR, value); + } + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/EndOfFinancialMonth.java b/source/java/org/alfresco/repo/dictionary/types/period/EndOfFinancialMonth.java new file mode 100644 index 0000000000..0941de42f3 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/EndOfFinancialMonth.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.dictionary.types.period; + +/** + * End of financial month + * @author andyh + * + */ +public class EndOfFinancialMonth extends EndOfMonth +{ + /** + * + */ + public static final String PERIOD_TYPE = "fmend"; + + + public String getPeriodType() + { + return PERIOD_TYPE; + } + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/EndOfFinancialQuarter.java b/source/java/org/alfresco/repo/dictionary/types/period/EndOfFinancialQuarter.java new file mode 100644 index 0000000000..c93c58010f --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/EndOfFinancialQuarter.java @@ -0,0 +1,44 @@ +/* + * 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.dictionary.types.period; + +/** + * End of financial quarter + * @author andyh + * + */ +public class EndOfFinancialQuarter extends EndOfQuarter +{ + /** + * + */ + public static final String PERIOD_TYPE = "fqend"; + + + public String getPeriodType() + { + return PERIOD_TYPE; + } +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/EndOfFinancialYear.java b/source/java/org/alfresco/repo/dictionary/types/period/EndOfFinancialYear.java new file mode 100644 index 0000000000..624af2a73e --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/EndOfFinancialYear.java @@ -0,0 +1,44 @@ +/* + * 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.dictionary.types.period; + +/** + * End of financial year + * @author andyh + * + */ +public class EndOfFinancialYear extends EndOfYear +{ + /** + * + */ + public static final String PERIOD_TYPE = "fyend"; + + + public String getPeriodType() + { + return PERIOD_TYPE; + } +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/EndOfMonth.java b/source/java/org/alfresco/repo/dictionary/types/period/EndOfMonth.java new file mode 100644 index 0000000000..62781b4060 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/EndOfMonth.java @@ -0,0 +1,75 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; + +/** + * End of month + * @author andyh + * + */ +public class EndOfMonth extends AbstractEndOfCalendarPeriodProvider +{ + /** + * + */ + public static final String PERIOD_TYPE = "monthend"; + + @Override + public void add(Calendar calendar, int value) + { + // Add a milli to nudge roll over given a month end date + if (value > 0) + { + calendar.add(Calendar.MILLISECOND, 1); + } + + int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); + if(dayOfMonth < getStartDayOfMonth()) + { + calendar.add(Calendar.MONTH, value-1); + } + else + { + calendar.add(Calendar.MONTH, value); + } + + calendar.set(Calendar.DAY_OF_MONTH, getStartDayOfMonth()); + calendar.add(Calendar.DAY_OF_YEAR, -1); + + // Set the time one minute to midnight + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + } + + public String getPeriodType() + { + return PERIOD_TYPE; + } + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/EndOfQuarter.java b/source/java/org/alfresco/repo/dictionary/types/period/EndOfQuarter.java new file mode 100644 index 0000000000..934f0f8fd6 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/EndOfQuarter.java @@ -0,0 +1,84 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; + +/** + * End of quarter + * @author andyh + * + */ +public class EndOfQuarter extends AbstractEndOfCalendarPeriodProvider +{ + /** + * + */ + public static final String PERIOD_TYPE = "quarterend"; + + @Override + public void add(Calendar calendar, int value) + { + // Add a milli to nudge roll over given a quarter end date + if (value > 0) + { + calendar.add(Calendar.MILLISECOND, 1); + } + + int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); + int month = calendar.get(Calendar.MONTH); + int monthInYear = month - getStartMonth(); + if(monthInYear < 0) + { + monthInYear += 12; + } + int residualMonths = monthInYear % 3; + if(dayOfMonth < getStartDayOfMonth() && (residualMonths == 0)) + { + calendar.add(Calendar.MONTH, (value-1)*3); + + } + else + { + calendar.add(Calendar.MONTH, value*3); + } + + calendar.add(Calendar.MONTH, -residualMonths); + calendar.set(Calendar.DAY_OF_MONTH, getStartDayOfMonth()); + calendar.add(Calendar.DAY_OF_YEAR, -1); + + // Set the time one minute to midnight + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + } + + public String getPeriodType() + { + return PERIOD_TYPE; + } + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/EndOfYear.java b/source/java/org/alfresco/repo/dictionary/types/period/EndOfYear.java new file mode 100644 index 0000000000..2fcbc63972 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/EndOfYear.java @@ -0,0 +1,78 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; + +/** + * End of year + * @author andyh + * + */ +public class EndOfYear extends AbstractEndOfCalendarPeriodProvider +{ + /** + * + */ + public static final String PERIOD_TYPE = "yearend"; + + @Override + public void add(Calendar calendar, int value) + { + // Add a milli to nudge roll over given a year end date + if (value > 0) + { + calendar.add(Calendar.MILLISECOND, 1); + } + + int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); + int month = calendar.get(Calendar.MONTH); + if ((month < getStartMonth()) || ((dayOfMonth < getStartDayOfMonth()) && (month == getStartMonth()))) + { + calendar.add(Calendar.YEAR, value - 1); + } + else + { + calendar.add(Calendar.YEAR, value); + } + + calendar.set(Calendar.MONTH, getStartMonth()); + calendar.set(Calendar.DAY_OF_MONTH, getStartDayOfMonth()); + + calendar.add(Calendar.DAY_OF_YEAR, -1); + + // Set the time one minute to midnight + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + } + + public String getPeriodType() + { + return PERIOD_TYPE; + } + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/Months.java b/source/java/org/alfresco/repo/dictionary/types/period/Months.java new file mode 100644 index 0000000000..ee5376cae3 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/Months.java @@ -0,0 +1,52 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; + +/** + * Months + * @author andyh + * + */ +public class Months extends AbstractCalendarPeriodProvider +{ + /** + * + */ + public static final String PERIOD_TYPE = "month"; + + public String getPeriodType() + { + return PERIOD_TYPE; + } + + @Override + public void add(Calendar calendar, int value) + { + calendar.add(Calendar.MONTH, value); + } + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/NoPeriod.java b/source/java/org/alfresco/repo/dictionary/types/period/NoPeriod.java new file mode 100644 index 0000000000..d04c9f172f --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/NoPeriod.java @@ -0,0 +1,70 @@ +/* + * 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.dictionary.types.period; + +import java.util.Date; +/** + * No period + * Period type "none" + * @author andyh + * + */ +public class NoPeriod extends AbstractPeriodProvider +{ + /** + * + */ + public static final String PERIOD_TYPE = "none"; + + /** + * Default constructor + */ + public NoPeriod() + { + + } + + public String getDefaultExpression() + { + return null; + } + + public ExpressionMutiplicity getExpressionMutiplicity() + { + return ExpressionMutiplicity.NONE; + } + + public Date getNextDate(Date date, String expression) + { + return null; + } + + public String getPeriodType() + { + return PERIOD_TYPE; + } + + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/PeriodTest.java b/source/java/org/alfresco/repo/dictionary/types/period/PeriodTest.java new file mode 100644 index 0000000000..3e46022aa3 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/PeriodTest.java @@ -0,0 +1,853 @@ +/* + * 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.dictionary.types.period; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +import junit.framework.TestCase; + +import org.alfresco.service.cmr.repository.Period; +import org.alfresco.service.cmr.repository.PeriodProvider; +import org.alfresco.util.ApplicationContextHelper; +import org.alfresco.util.CachingDateFormat; + +/** + * Tests for period implementations - persistence and search is tested elsewhere + * + * @author andyh + */ +public class PeriodTest extends TestCase +{ + + @Override + protected void setUp() throws Exception + { + super.setUp(); + ApplicationContextHelper.getApplicationContext(); + } + + /** + * "none" + */ + public void testNoPeriod() + { + assertTrue(Period.getProviderNames().contains(NoPeriod.PERIOD_TYPE)); + Period period = new Period(NoPeriod.PERIOD_TYPE); + assertNull(period.getNextDate(new Date())); + + PeriodProvider provider = Period.getProvider(NoPeriod.PERIOD_TYPE); + assertNull(provider.getDefaultExpression()); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.NONE); + assertNull(provider.getNextDate(new Date(), null)); + assertNull(provider.getNextDate(new Date(), "")); + assertNull(provider.getNextDate(new Date(), "meep")); + assertEquals(provider.getPeriodType(), NoPeriod.PERIOD_TYPE); + } + + /** + * Days + */ + public void testDays() + { + assertTrue(Period.getProviderNames().contains(Days.PERIOD_TYPE)); + Period period = new Period(Days.PERIOD_TYPE); + Date now = new Date(); + assertNotNull(period.getNextDate(now)); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(now); + calendar.add(Calendar.DAY_OF_YEAR, 1); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Days.PERIOD_TYPE + "|0"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.DAY_OF_YEAR, 0); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Days.PERIOD_TYPE + "|1"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.DAY_OF_YEAR, 1); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Days.PERIOD_TYPE + "|2"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.DAY_OF_YEAR, 2); + assertEquals(period.getNextDate(now), calendar.getTime()); + + PeriodProvider provider = Period.getProvider(Days.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertNotNull(provider.getNextDate(now, "0")); + assertNotNull(provider.getNextDate(now, "1")); + assertNotNull(provider.getNextDate(now, "2")); + assertEquals(provider.getPeriodType(), Days.PERIOD_TYPE); + } + + /** + * Weeks + */ + public void testWeeks() + { + assertTrue(Period.getProviderNames().contains(Weeks.PERIOD_TYPE)); + Period period = new Period(Weeks.PERIOD_TYPE); + Date now = new Date(); + assertNotNull(period.getNextDate(now)); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(now); + calendar.add(Calendar.WEEK_OF_YEAR, 1); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Weeks.PERIOD_TYPE + "|0"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.WEEK_OF_YEAR, 0); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Weeks.PERIOD_TYPE + "|1"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.WEEK_OF_YEAR, 1); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Weeks.PERIOD_TYPE + "|2"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.WEEK_OF_YEAR, 2); + assertEquals(period.getNextDate(now), calendar.getTime()); + + PeriodProvider provider = Period.getProvider(Weeks.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertNotNull(provider.getNextDate(now, "0")); + assertNotNull(provider.getNextDate(now, "1")); + assertNotNull(provider.getNextDate(now, "2")); + assertEquals(provider.getPeriodType(), Weeks.PERIOD_TYPE); + } + + /** + * Months + */ + public void testMonths() + { + assertTrue(Period.getProviderNames().contains(Months.PERIOD_TYPE)); + Period period = new Period(Months.PERIOD_TYPE); + Date now = new Date(); + assertNotNull(period.getNextDate(now)); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 1); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Months.PERIOD_TYPE + "|0"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 0); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Months.PERIOD_TYPE + "|1"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 1); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Months.PERIOD_TYPE + "|2"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 2); + assertEquals(period.getNextDate(now), calendar.getTime()); + + PeriodProvider provider = Period.getProvider(Months.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertNotNull(provider.getNextDate(now, "0")); + assertNotNull(provider.getNextDate(now, "1")); + assertNotNull(provider.getNextDate(now, "2")); + assertEquals(provider.getPeriodType(), Months.PERIOD_TYPE); + } + + /** + * Quarters + */ + public void testQuarters() + { + assertTrue(Period.getProviderNames().contains(Quarters.PERIOD_TYPE)); + Period period = new Period(Quarters.PERIOD_TYPE); + Date now = new Date(); + assertNotNull(period.getNextDate(now)); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 3); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Quarters.PERIOD_TYPE + "|0"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 0); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Quarters.PERIOD_TYPE + "|1"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 3); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Quarters.PERIOD_TYPE + "|2"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 6); + assertEquals(period.getNextDate(now), calendar.getTime()); + + PeriodProvider provider = Period.getProvider(Quarters.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertNotNull(provider.getNextDate(now, "0")); + assertNotNull(provider.getNextDate(now, "1")); + assertNotNull(provider.getNextDate(now, "2")); + assertEquals(provider.getPeriodType(), Quarters.PERIOD_TYPE); + } + + /** + * Years + */ + public void testYears() + { + assertTrue(Period.getProviderNames().contains(Years.PERIOD_TYPE)); + Period period = new Period(Years.PERIOD_TYPE); + Date now = new Date(); + assertNotNull(period.getNextDate(now)); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(now); + calendar.add(Calendar.YEAR, 1); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Years.PERIOD_TYPE + "|0"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.YEAR, 0); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Years.PERIOD_TYPE + "|1"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.YEAR, 1); + assertEquals(period.getNextDate(now), calendar.getTime()); + + period = new Period(Years.PERIOD_TYPE + "|2"); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.YEAR, 2); + assertEquals(period.getNextDate(now), calendar.getTime()); + + PeriodProvider provider = Period.getProvider(Years.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertNotNull(provider.getNextDate(now, "0")); + assertNotNull(provider.getNextDate(now, "1")); + assertNotNull(provider.getNextDate(now, "2")); + assertEquals(provider.getPeriodType(), Years.PERIOD_TYPE); + } + + /** + * EndOfMonth + */ + public void testEndOfMonth() + { + assertTrue(Period.getProviderNames().contains(EndOfMonth.PERIOD_TYPE)); + Period period = new Period(EndOfMonth.PERIOD_TYPE); + Date now = new Date(); + assertNotNull(period.getNextDate(now)); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 1); + calendar.set(Calendar.DAY_OF_MONTH, 1); + calendar.add(Calendar.DAY_OF_MONTH, -1); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + assertEquals(period.getNextDate(now), calendar.getTime()); + + for (int i = -100; i < 100; i++) + { + period = new Period(EndOfMonth.PERIOD_TYPE + "|" + i); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.MONTH, i); + calendar.set(Calendar.DAY_OF_MONTH, 1); + calendar.add(Calendar.DAY_OF_MONTH, -1); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + assertEquals(period.getNextDate(now), calendar.getTime()); + } + + PeriodProvider provider = Period.getProvider(EndOfMonth.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertNotNull(provider.getNextDate(now, "0")); + assertNotNull(provider.getNextDate(now, "1")); + assertNotNull(provider.getNextDate(now, "2")); + assertEquals(provider.getPeriodType(), EndOfMonth.PERIOD_TYPE); + } + + /** + * EndOfYear + */ + public void testEndOfYear() + { + assertTrue(Period.getProviderNames().contains(EndOfYear.PERIOD_TYPE)); + Period period = new Period(EndOfYear.PERIOD_TYPE); + Date now = new Date(); + assertNotNull(period.getNextDate(now)); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(now); + calendar.add(Calendar.YEAR, 1); + calendar.set(Calendar.DAY_OF_YEAR, 1); + calendar.add(Calendar.DAY_OF_YEAR, -1); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + assertEquals(period.getNextDate(now), calendar.getTime()); + + for (int i = -100; i < 100; i++) + { + period = new Period(EndOfYear.PERIOD_TYPE + "|" + i); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.YEAR, i); + calendar.set(Calendar.DAY_OF_YEAR, 1); + calendar.add(Calendar.DAY_OF_YEAR, -1); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + assertEquals(period.getNextDate(now), calendar.getTime()); + } + + PeriodProvider provider = Period.getProvider(EndOfYear.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertNotNull(provider.getNextDate(now, "0")); + assertNotNull(provider.getNextDate(now, "1")); + assertNotNull(provider.getNextDate(now, "2")); + assertEquals(provider.getPeriodType(), EndOfYear.PERIOD_TYPE); + } + + /** + * End of Quarter + * + * @throws ParseException + */ + public void testEndOfQuarter() throws ParseException + { + PeriodProvider provider = Period.getProvider(EndOfQuarter.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertEquals(provider.getPeriodType(), EndOfQuarter.PERIOD_TYPE); + + SimpleDateFormat df = CachingDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", true); + Period period = new Period(EndOfQuarter.PERIOD_TYPE); + Date date; + date = df.parse("2009-01-01T00:00:00.000"); + assertEquals("2009-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-03-31T00:00:00.000"); + assertEquals("2009-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-01T00:00:00.000"); + assertEquals("2009-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-01T00:00:00.000"); + assertEquals("2009-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-30T23:59:59.999"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-07-01T23:59:59.999"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.998"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.999"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-10-01T23:59:00.000"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-12-31T23:59:00.000"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + + period = new Period(EndOfQuarter.PERIOD_TYPE + "|2"); + date = df.parse("2009-01-01T00:00:00.000"); + assertEquals("2009-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-03-31T00:00:00.000"); + assertEquals("2009-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-01T00:00:00.000"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-01T00:00:00.000"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-30T23:59:59.999"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-07-01T23:59:59.999"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.999"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-10-01T23:59:00.000"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-12-31T23:59:00.000"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + + period = new Period(EndOfQuarter.PERIOD_TYPE + "|3"); + date = df.parse("2009-01-01T00:00:00.000"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-03-31T00:00:00.000"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-01T00:00:00.000"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-01T00:00:00.000"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-30T23:59:59.999"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-07-01T23:59:59.999"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.999"); + assertEquals("2010-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-10-01T23:59:00.000"); + assertEquals("2010-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-12-31T23:59:00.000"); + assertEquals("2010-06-30T23:59:59.999", df.format(period.getNextDate(date))); + + period = new Period(EndOfQuarter.PERIOD_TYPE + "|4"); + date = df.parse("2009-01-01T00:00:00.000"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-03-31T00:00:00.000"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-01T00:00:00.000"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-01T00:00:00.000"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-30T23:59:59.999"); + assertEquals("2010-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-07-01T23:59:59.999"); + assertEquals("2010-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.999"); + assertEquals("2010-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-10-01T23:59:00.000"); + assertEquals("2010-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-12-31T23:59:00.000"); + assertEquals("2010-09-30T23:59:59.999", df.format(period.getNextDate(date))); + + period = new Period(EndOfQuarter.PERIOD_TYPE + "|5"); + date = df.parse("2009-01-01T00:00:00.000"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-03-31T00:00:00.000"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-01T00:00:00.000"); + assertEquals("2010-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-01T00:00:00.000"); + assertEquals("2010-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-30T23:59:59.999"); + assertEquals("2010-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-07-01T23:59:59.999"); + assertEquals("2010-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.999"); + assertEquals("2010-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-10-01T23:59:00.000"); + assertEquals("2010-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-12-31T23:59:00.000"); + assertEquals("2010-12-31T23:59:59.999", df.format(period.getNextDate(date))); + } + + /** + * End of F Month For 1 Oct this is the same as month + */ + public void testEndOfDefaultFinancialMonth() + { + assertTrue(Period.getProviderNames().contains(EndOfFinancialMonth.PERIOD_TYPE)); + Period period = new Period(EndOfFinancialMonth.PERIOD_TYPE); + Date now = new Date(); + assertNotNull(period.getNextDate(now)); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(now); + calendar.add(Calendar.MONTH, 1); + calendar.set(Calendar.DAY_OF_MONTH, 1); + calendar.add(Calendar.DAY_OF_MONTH, -1); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + assertEquals(period.getNextDate(now), calendar.getTime()); + + for (int i = -100; i < 100; i++) + { + period = new Period(EndOfFinancialMonth.PERIOD_TYPE + "|" + i); + assertNotNull(period.getNextDate(now)); + calendar.setTime(now); + calendar.add(Calendar.MONTH, i); + calendar.set(Calendar.DAY_OF_MONTH, 1); + calendar.add(Calendar.DAY_OF_MONTH, -1); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + assertEquals(period.getNextDate(now), calendar.getTime()); + } + + PeriodProvider provider = Period.getProvider(EndOfFinancialMonth.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertNotNull(provider.getNextDate(now, "0")); + assertNotNull(provider.getNextDate(now, "1")); + assertNotNull(provider.getNextDate(now, "2")); + assertEquals(provider.getPeriodType(), EndOfFinancialMonth.PERIOD_TYPE); + } + + /** + * EndOfFinacialYear + * + * @throws ParseException + */ + public void testEndOfDefaultFinancialYear() throws ParseException + { + PeriodProvider provider = Period.getProvider(EndOfFinancialYear.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertEquals(provider.getPeriodType(), EndOfFinancialYear.PERIOD_TYPE); + + SimpleDateFormat df = CachingDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", true); + Period period = new Period(EndOfFinancialYear.PERIOD_TYPE); + Date date; + date = df.parse("2008-10-01T00:00:00.000"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.998"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.999"); + assertEquals("2010-09-30T23:59:59.999", df.format(period.getNextDate(date))); + + period = new Period(EndOfFinancialYear.PERIOD_TYPE + "|10"); + date = df.parse("2008-10-01T00:00:00.000"); + assertEquals("2018-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.998"); + assertEquals("2018-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.999"); + assertEquals("2019-09-30T23:59:59.999", df.format(period.getNextDate(date))); + + } + + /** + * End of FQ + * + * @throws ParseException + */ + public void testEndOfDefaultFinancialQuarter() throws ParseException + { + PeriodProvider provider = Period.getProvider(EndOfFinancialQuarter.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertEquals(provider.getPeriodType(), EndOfFinancialQuarter.PERIOD_TYPE); + + SimpleDateFormat df = CachingDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", true); + Period period = new Period(EndOfFinancialQuarter.PERIOD_TYPE); + Date date; + date = df.parse("2008-10-01T00:00:00.000"); + assertEquals("2008-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-12-31T23:59:59.998"); + assertEquals("2008-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-12-31T23:59:59.999"); + assertEquals("2009-03-31T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-01-01T00:00:00.000"); + assertEquals("2009-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-03-31T23:59:59.998"); + assertEquals("2009-03-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-03-31T23:59:59.999"); + assertEquals("2009-06-30T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-04-01T00:00:00.000"); + assertEquals("2009-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-30T23:59:59.998"); + assertEquals("2009-06-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-06-30T23:59:59.999"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-07-01T00:00:00.000"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.998"); + assertEquals("2009-09-30T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-09-30T23:59:59.999"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-10-01T00:00:00.000"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-12-31T23:59:59.998"); + assertEquals("2009-12-31T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-12-31T23:59:59.999"); + assertEquals("2010-03-31T23:59:59.999", df.format(period.getNextDate(date))); + } + + /** + * EndOfFinacialYear + * + * @throws ParseException + */ + public void testEndOfUKTaxYear() throws ParseException + { + PeriodProvider provider = Period.getProvider(EndOfFinancialYear.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertEquals(provider.getPeriodType(), EndOfFinancialYear.PERIOD_TYPE); + + AbstractEndOfCalendarPeriodProvider instance = (AbstractEndOfCalendarPeriodProvider) provider; + instance.setStartDayOfMonth(6); + instance.setStartMonth(Calendar.APRIL); + + SimpleDateFormat df = CachingDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", true); + Period period = new Period(EndOfFinancialYear.PERIOD_TYPE); + Date date; + date = df.parse("2008-4-06T00:00:00.000"); + assertEquals("2009-04-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-05T23:59:59.998"); + assertEquals("2009-04-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-05T23:59:59.999"); + assertEquals("2010-04-05T23:59:59.999", df.format(period.getNextDate(date))); + + period = new Period(EndOfFinancialYear.PERIOD_TYPE + "|10"); + date = df.parse("2008-4-06T00:00:00.000"); + assertEquals("2018-04-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-05T23:59:59.998"); + assertEquals("2018-04-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-05T23:59:59.999"); + assertEquals("2019-04-05T23:59:59.999", df.format(period.getNextDate(date))); + + } + + /** + * End of FQ + * + * @throws ParseException + */ + public void testEndOfUKTaxQuarter() throws ParseException + { + PeriodProvider provider = Period.getProvider(EndOfFinancialQuarter.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertEquals(provider.getPeriodType(), EndOfFinancialQuarter.PERIOD_TYPE); + + AbstractEndOfCalendarPeriodProvider instance = (AbstractEndOfCalendarPeriodProvider) provider; + instance.setStartDayOfMonth(6); + instance.setStartMonth(Calendar.APRIL); + + SimpleDateFormat df = CachingDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", true); + Period period = new Period(EndOfFinancialQuarter.PERIOD_TYPE); + Date date; + date = df.parse("2008-04-06T00:00:00.000"); + assertEquals("2008-07-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-07-05T23:59:59.998"); + assertEquals("2008-07-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-07-05T23:59:59.999"); + assertEquals("2008-10-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-07-06T00:00:00.000"); + assertEquals("2008-10-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-10-05T23:59:59.998"); + assertEquals("2008-10-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-10-05T23:59:59.999"); + assertEquals("2009-01-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-10-06T00:00:00.000"); + assertEquals("2009-01-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-01-05T23:59:59.998"); + assertEquals("2009-01-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-01-05T23:59:59.999"); + assertEquals("2009-04-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-01-06T00:00:00.000"); + assertEquals("2009-04-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-05T23:59:59.998"); + assertEquals("2009-04-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-05T23:59:59.999"); + assertEquals("2009-07-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-04-06T00:00:00.000"); + assertEquals("2009-07-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-07-05T23:59:59.998"); + assertEquals("2009-07-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-07-05T23:59:59.999"); + assertEquals("2009-10-05T23:59:59.999", df.format(period.getNextDate(date))); + } + + /** + * End of FQ + * + * @throws ParseException + */ + public void testEndOfUKTaxMonth() throws ParseException + { + PeriodProvider provider = Period.getProvider(EndOfFinancialMonth.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "1"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.OPTIONAL); + assertEquals(provider.getPeriodType(), EndOfFinancialMonth.PERIOD_TYPE); + + AbstractEndOfCalendarPeriodProvider instance = (AbstractEndOfCalendarPeriodProvider) provider; + instance.setStartDayOfMonth(6); + instance.setStartMonth(Calendar.APRIL); + + SimpleDateFormat df = CachingDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", true); + Period period = new Period(EndOfFinancialMonth.PERIOD_TYPE); + Date date; + date = df.parse("2008-04-06T00:00:00.000"); + assertEquals("2008-05-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-05-05T23:59:59.998"); + assertEquals("2008-05-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-05-05T23:59:59.999"); + assertEquals("2008-06-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-05-06T00:00:00.000"); + assertEquals("2008-06-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-06-05T23:59:59.998"); + assertEquals("2008-06-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-06-05T23:59:59.999"); + assertEquals("2008-07-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-06-06T00:00:00.000"); + assertEquals("2008-07-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-07-05T23:59:59.998"); + assertEquals("2008-07-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-07-05T23:59:59.999"); + assertEquals("2008-08-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-07-06T00:00:00.000"); + assertEquals("2008-08-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-08-05T23:59:59.998"); + assertEquals("2008-08-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-08-05T23:59:59.999"); + assertEquals("2008-09-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-08-06T00:00:00.000"); + assertEquals("2008-09-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-09-05T23:59:59.998"); + assertEquals("2008-09-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-09-05T23:59:59.999"); + assertEquals("2008-10-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-09-06T00:00:00.000"); + assertEquals("2008-10-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-10-05T23:59:59.998"); + assertEquals("2008-10-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-10-05T23:59:59.999"); + assertEquals("2008-11-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-10-06T00:00:00.000"); + assertEquals("2008-11-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-11-05T23:59:59.998"); + assertEquals("2008-11-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-11-05T23:59:59.999"); + assertEquals("2008-12-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-11-06T00:00:00.000"); + assertEquals("2008-12-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-12-05T23:59:59.998"); + assertEquals("2008-12-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2008-12-05T23:59:59.999"); + assertEquals("2009-01-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2008-12-06T00:00:00.000"); + assertEquals("2009-01-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-01-05T23:59:59.998"); + assertEquals("2009-01-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-01-05T23:59:59.999"); + assertEquals("2009-02-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-01-06T00:00:00.000"); + assertEquals("2009-02-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-02-05T23:59:59.998"); + assertEquals("2009-02-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-02-05T23:59:59.999"); + assertEquals("2009-03-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-02-06T00:00:00.000"); + assertEquals("2009-03-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-03-05T23:59:59.998"); + assertEquals("2009-03-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-03-05T23:59:59.999"); + assertEquals("2009-04-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-03-06T00:00:00.000"); + assertEquals("2009-04-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-05T23:59:59.998"); + assertEquals("2009-04-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-04-05T23:59:59.999"); + assertEquals("2009-05-05T23:59:59.999", df.format(period.getNextDate(date))); + + date = df.parse("2009-04-06T00:00:00.000"); + assertEquals("2009-05-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-05-05T23:59:59.998"); + assertEquals("2009-05-05T23:59:59.999", df.format(period.getNextDate(date))); + date = df.parse("2009-05-05T23:59:59.999"); + assertEquals("2009-06-05T23:59:59.999", df.format(period.getNextDate(date))); + } + + /** + * Cron + * @throws ParseException + */ + public void testCron() throws ParseException + { + PeriodProvider provider = Period.getProvider(Cron.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "59 59 23 * * ?"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.MANDATORY); + assertEquals(provider.getPeriodType(), Cron.PERIOD_TYPE); + + SimpleDateFormat df = CachingDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", true); + Period period = new Period(Cron.PERIOD_TYPE); + Date date; + date = df.parse("2009-06-02T00:00:00.000"); + assertEquals("2009-06-02T23:59:59.000", df.format(period.getNextDate(date))); + + period = new Period(Cron.PERIOD_TYPE+"|0 0 2 ? * 6#1"); // First Friday of month + assertEquals("2009-06-05T02:00:00.000", df.format(period.getNextDate(date))); + } + + /** + * XMLDuration + * @throws ParseException + */ + public void testXMLDuration() throws ParseException + { + PeriodProvider provider = Period.getProvider(XMLDuration.PERIOD_TYPE); + assertEquals(provider.getDefaultExpression(), "P1D"); + assertEquals(provider.getExpressionMutiplicity(), PeriodProvider.ExpressionMutiplicity.MANDATORY); + assertEquals(provider.getPeriodType(), XMLDuration.PERIOD_TYPE); + + SimpleDateFormat df = CachingDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", true); + Period period = new Period(XMLDuration.PERIOD_TYPE); + Date date; + date = df.parse("2009-06-02T01:02:03.004"); + assertEquals("2009-06-03T01:02:03.004", df.format(period.getNextDate(date))); + + period = new Period(XMLDuration.PERIOD_TYPE+"|P2Y6M5DT12H35M30.100S"); // First Friday of month + assertEquals("2011-12-07T13:37:33.104", df.format(period.getNextDate(date))); + } + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/Quarters.java b/source/java/org/alfresco/repo/dictionary/types/period/Quarters.java new file mode 100644 index 0000000000..f1d9514e05 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/Quarters.java @@ -0,0 +1,51 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; + +/** + * Quarters + * @author andyh + * + */ +public class Quarters extends AbstractCalendarPeriodProvider +{ + /** + * + */ + public static final String PERIOD_TYPE = "quarter"; + + public String getPeriodType() + { + return PERIOD_TYPE; + } + + @Override + public void add(Calendar calendar, int value) + { + calendar.add(Calendar.MONTH, value*3); + } +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/Weeks.java b/source/java/org/alfresco/repo/dictionary/types/period/Weeks.java new file mode 100644 index 0000000000..07c3f0bebb --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/Weeks.java @@ -0,0 +1,50 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; +/** + * Weeks + * @author andyh + * + */ +public class Weeks extends AbstractCalendarPeriodProvider +{ + /** + * + */ + public static final String PERIOD_TYPE = "week"; + + public String getPeriodType() + { + return PERIOD_TYPE; + } + + @Override + public void add(Calendar calendar, int value) + { + calendar.add(Calendar.WEEK_OF_YEAR, value); + } +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/XMLDuration.java b/source/java/org/alfresco/repo/dictionary/types/period/XMLDuration.java new file mode 100644 index 0000000000..fa23495fd4 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/XMLDuration.java @@ -0,0 +1,40 @@ +package org.alfresco.repo.dictionary.types.period; + +import java.util.Date; + +import org.alfresco.service.cmr.repository.datatype.Duration; + +/** + * XMLDuration + * @author andyh + * + */ +public class XMLDuration extends AbstractPeriodProvider +{ + /** + * Period type + */ + public static final String PERIOD_TYPE = "duration"; + + public String getDefaultExpression() + { + return "P1D"; + } + + public ExpressionMutiplicity getExpressionMutiplicity() + { + return ExpressionMutiplicity.MANDATORY; + } + + public Date getNextDate(Date date, String expression) + { + Duration d = new Duration(expression); + return Duration.add(date, d); + } + + public String getPeriodType() + { + return PERIOD_TYPE; + } + +} diff --git a/source/java/org/alfresco/repo/dictionary/types/period/Years.java b/source/java/org/alfresco/repo/dictionary/types/period/Years.java new file mode 100644 index 0000000000..7dabd3ed61 --- /dev/null +++ b/source/java/org/alfresco/repo/dictionary/types/period/Years.java @@ -0,0 +1,51 @@ +/* + * 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.dictionary.types.period; + +import java.util.Calendar; + +/** + * Years + * @author andyh + * + */ +public class Years extends AbstractCalendarPeriodProvider +{ + /** + * + */ + public static final String PERIOD_TYPE = "year"; + + public String getPeriodType() + { + return PERIOD_TYPE; + } + + @Override + public void add(Calendar calendar, int value) + { + calendar.add(Calendar.YEAR, value); + } +} diff --git a/source/java/org/alfresco/repo/domain/NodePropertyValue.java b/source/java/org/alfresco/repo/domain/NodePropertyValue.java index d084ce92d6..d75e3b707c 100644 --- a/source/java/org/alfresco/repo/domain/NodePropertyValue.java +++ b/source/java/org/alfresco/repo/domain/NodePropertyValue.java @@ -45,6 +45,7 @@ import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.MLText; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.Period; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.namespace.QName; import org.alfresco.util.EqualsHelper; @@ -453,7 +454,28 @@ public class NodePropertyValue implements Cloneable, Serializable return value; } } - }; + }, + PERIOD + { + @Override + public Integer getOrdinalNumber() + { + return Integer.valueOf(20); + } + + @Override + protected ValueType getPersistedType(Serializable value) + { + return ValueType.STRING; + } + + @Override + Serializable convert(Serializable value) + { + return DefaultTypeConverter.INSTANCE.convert(Period.class, value); + } + } + ; /** * @return Returns the manually-maintained ordinal number for the value @@ -555,6 +577,10 @@ public class NodePropertyValue implements Cloneable, Serializable { return ValueType.MLTEXT; } + else if (value instanceof Period) + { + return ValueType.PERIOD; + } else { // type is not recognised as belonging to any particular slot @@ -590,6 +616,7 @@ public class NodePropertyValue implements Cloneable, Serializable valueTypesByPropertyType.put(DataTypeDefinition.PATH, ValueType.PATH); valueTypesByPropertyType.put(DataTypeDefinition.QNAME, ValueType.QNAME); valueTypesByPropertyType.put(DataTypeDefinition.LOCALE, ValueType.LOCALE); + valueTypesByPropertyType.put(DataTypeDefinition.PERIOD, ValueType.PERIOD); valueTypesByOrdinalNumber = new HashMap(37); for (ValueType valueType : ValueType.values()) diff --git a/source/java/org/alfresco/repo/domain/PropertyValue.java b/source/java/org/alfresco/repo/domain/PropertyValue.java index fa8c9a0cac..51b03c534a 100644 --- a/source/java/org/alfresco/repo/domain/PropertyValue.java +++ b/source/java/org/alfresco/repo/domain/PropertyValue.java @@ -48,6 +48,7 @@ import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.MLText; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.Period; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.namespace.QName; import org.alfresco.util.EqualsHelper; @@ -441,6 +442,26 @@ public class PropertyValue implements Cloneable, Serializable { return DefaultTypeConverter.INSTANCE.convert(VersionNumber.class, value); } + }, + PERIOD + { + @Override + public Integer getOrdinalNumber() + { + return Integer.valueOf(20); + } + + @Override + protected ValueType getPersistedType(Serializable value) + { + return ValueType.STRING; + } + + @Override + Serializable convert(Serializable value) + { + return DefaultTypeConverter.INSTANCE.convert(Period.class, value); + } }; /** @@ -567,6 +588,10 @@ public class PropertyValue implements Cloneable, Serializable { return ValueType.MLTEXT; } + else if (value instanceof Period) + { + return ValueType.PERIOD; + } else { // type is not recognised as belonging to any particular slot @@ -602,6 +627,7 @@ public class PropertyValue implements Cloneable, Serializable valueTypesByPropertyType.put(DataTypeDefinition.PATH, ValueType.PATH); valueTypesByPropertyType.put(DataTypeDefinition.QNAME, ValueType.QNAME); valueTypesByPropertyType.put(DataTypeDefinition.LOCALE, ValueType.LOCALE); + valueTypesByPropertyType.put(DataTypeDefinition.PERIOD, ValueType.PERIOD); valueTypesByOrdinalNumber = new HashMap(37); for (ValueType valueType : ValueType.values()) diff --git a/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java b/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java index 6e918687d5..d395aa201e 100644 --- a/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java +++ b/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java @@ -129,7 +129,8 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest public static final QName PROP_QNAME_CATEGORY_VALUE = QName.createQName(NAMESPACE, "categoryValue"); public static final QName PROP_QNAME_LOCALE_VALUE = QName.createQName(NAMESPACE, "localeValue"); public static final QName PROP_QNAME_NULL_VALUE = QName.createQName(NAMESPACE, "nullValue"); - public static final QName PROP_QNAME_MULTI_VALUE = QName.createQName(NAMESPACE, "multiValue"); + public static final QName PROP_QNAME_MULTI_VALUE = QName.createQName(NAMESPACE, "multiValue"); + public static final QName PROP_QNAME_PERIOD_VALUE = QName.createQName(NAMESPACE, "periodValue"); public static final QName PROP_QNAME_MULTI_ML_VALUE = QName.createQName(NAMESPACE, "multiMLValue"); public static final QName PROP_QNAME_MARKER_PROP = QName.createQName(NAMESPACE, "markerProp"); public static final QName PROP_QNAME_PROP1 = QName.createQName(NAMESPACE, "prop1"); @@ -1533,6 +1534,7 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest properties.put(PROP_QNAME_LOCALE_VALUE, Locale.CHINESE); properties.put(PROP_QNAME_NULL_VALUE, null); properties.put(PROP_QNAME_MULTI_VALUE, listProperty); + properties.put(PROP_QNAME_PERIOD_VALUE, "period|1"); // Get the check values Map expectedProperties = new HashMap(properties); getExpectedPropertyValues(expectedProperties); 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 d45568dcd7..fb0504512c 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java @@ -81,6 +81,7 @@ import org.alfresco.service.cmr.repository.MLText; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.Period; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.repository.datatype.Duration; @@ -314,6 +315,7 @@ public class ADMLuceneTest extends TestCase testProperties.put(QName.createQName(TEST_NAMESPACE, "noderef-ista"), n1); testProperties.put(QName.createQName(TEST_NAMESPACE, "path-ista"), nodeService.getPath(n3)); testProperties.put(QName.createQName(TEST_NAMESPACE, "locale-ista"), Locale.UK); + testProperties.put(QName.createQName(TEST_NAMESPACE, "period-ista"), new Period("period|12")); testProperties.put(QName.createQName(TEST_NAMESPACE, "null"), null); testProperties.put(QName.createQName(TEST_NAMESPACE, "list"), new ArrayList()); MLText mlText = new MLText(); @@ -3877,6 +3879,14 @@ public class ADMLuceneTest extends TestCase assertNotNull(results.getRow(0).getValue(QName.createQName(TEST_NAMESPACE, "path-ista"))); results.close(); + // Period + + results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "\\@" + escapeQName(QName.createQName(TEST_NAMESPACE, "period-ista")) + ":\"period|12\"", null); + assertEquals(1, results.length()); + assertNotNull(results.getRow(0).getValue(QName.createQName(TEST_NAMESPACE, "path-ista"))); + results.close(); + + // Type results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "TYPE:\"" + testType.toString() + "\"", null); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneTest_model.xml b/source/java/org/alfresco/repo/search/impl/lucene/LuceneTest_model.xml index fe377b1e5f..bb50836283 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneTest_model.xml +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneTest_model.xml @@ -320,6 +320,16 @@ true true + + + d:period + false + false + + true + true + true + diff --git a/source/java/org/alfresco/service/cmr/dictionary/DataTypeDefinition.java b/source/java/org/alfresco/service/cmr/dictionary/DataTypeDefinition.java index 88da68f1b5..14ecd0a92c 100644 --- a/source/java/org/alfresco/service/cmr/dictionary/DataTypeDefinition.java +++ b/source/java/org/alfresco/service/cmr/dictionary/DataTypeDefinition.java @@ -58,6 +58,7 @@ public interface DataTypeDefinition public QName ASSOC_REF = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "assocref"); public QName PATH = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "path"); public QName LOCALE = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "locale"); + public QName PERIOD = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "period"); /** diff --git a/source/java/org/alfresco/service/cmr/repository/Period.java b/source/java/org/alfresco/service/cmr/repository/Period.java new file mode 100644 index 0000000000..9a4acfaa3c --- /dev/null +++ b/source/java/org/alfresco/service/cmr/repository/Period.java @@ -0,0 +1,167 @@ +/* + * 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.service.cmr.repository; + +import java.io.Serializable; +import java.util.Date; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Implementation for the period data type "d:period" A period is specified by the period type and an optional + * expression. The string value is periodType|expression Examples are: none day - one day day|3 - 3 days week - one week + * week|1 - one week week|2 - two weeks month year monthend quarterend The period type specifies a period + * implementation. This is registered with this class and is used to when adding the period to a date, handles any + * processing of the expression, reports if the expression is not required, optional or mandatory. + * + * @author andyh + */ +@SuppressWarnings("unchecked") +public class Period implements Serializable +{ + /** + * + */ + private static final long serialVersionUID = -7978001474638355909L; + + // Providers do not serialize + transient private static ConcurrentHashMap providers = new ConcurrentHashMap(); + + /** + * Register a provider + * @param periodProvider + */ + public static void registerProvider(PeriodProvider periodProvider) + { + providers.put(periodProvider.getPeriodType(), periodProvider); + } + + /** + * Find a provider + * @param periodType + * @return the provider + * @throws IllegalStateException of there is no implementation + */ + public static PeriodProvider getProvider(String periodType) + { + PeriodProvider provider = providers.get(periodType); + if (provider == null) + { + throw new IllegalStateException("No period provider for period type " + periodType); + } + return provider; + } + + /** + * Get the set of registered providers + * @return - the set of registered providers + */ + public static Set getProviderNames() + { + return providers.keySet(); + } + + private String periodType; + + private String expression; + + /** + * Create a period without an accompanying expression. + * + * @param period + */ + public Period(String period) + { + String[] parts = period.split("\\|", 2); + periodType = parts[0]; + if (parts.length == 2) + { + expression = parts[1]; + } + } + + /** + * Calculate the next date for this period given the a start date. + * + * @param date + * @return the next date. + */ + public Date getNextDate(Date date) + { + PeriodProvider provider = getProvider(periodType); + return provider.getNextDate(date, expression != null ? expression : provider.getDefaultExpression()); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((expression == null) ? 0 : expression.hashCode()); + result = prime * result + ((periodType == null) ? 0 : periodType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Period other = (Period) obj; + if (expression == null) + { + if (other.expression != null) + return false; + } + else if (!expression.equals(other.expression)) + return false; + if (periodType == null) + { + if (other.periodType != null) + return false; + } + else if (!periodType.equals(other.periodType)) + return false; + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append(periodType); + if (expression != null) + { + builder.append("|"); + builder.append(expression); + } + return builder.toString(); + } + +} diff --git a/source/java/org/alfresco/service/cmr/repository/PeriodProvider.java b/source/java/org/alfresco/service/cmr/repository/PeriodProvider.java new file mode 100644 index 0000000000..5a109d1eb9 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/repository/PeriodProvider.java @@ -0,0 +1,82 @@ +/* + * 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.service.cmr.repository; + +import java.util.Date; + +/** + * Provider API for period implementations + * @author andyh + * + */ +public interface PeriodProvider +{ + /** + * Period expression multiplicity + * @author andyh + * + */ + public enum ExpressionMutiplicity + { + /** + * There is no expression + */ + NONE, + /** + * An expression is optional + */ + OPTIONAL, + /** + * An expression is mandatory + */ + MANDATORY + } + + /** + * Get the name for the period. + * @return - period name + */ + public String getPeriodType(); + + /** + * Get the next date - the provided date + period + * @param date + * @param expression + * @return the next date in the period + */ + public Date getNextDate(Date date, String expression); + + /** + * Is the expression required etc ... + * @return the multiplicity + */ + public ExpressionMutiplicity getExpressionMutiplicity(); + + /** + * Get the default expression - this could be null + * @return - the default expression. + */ + public String getDefaultExpression(); +} diff --git a/source/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java b/source/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java index 41ba24dd58..13a859e2ad 100644 --- a/source/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java +++ b/source/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java @@ -53,6 +53,7 @@ import org.alfresco.service.cmr.repository.EntityRef; import org.alfresco.service.cmr.repository.MLText; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.Period; import org.alfresco.service.namespace.QName; import org.alfresco.util.ISO8601DateFormat; import org.alfresco.util.VersionNumber; @@ -291,6 +292,14 @@ public class DefaultTypeConverter } }); + INSTANCE.addConverter(String.class, Period.class, new TypeConverter.Converter() + { + public Period convert(String source) + { + return new Period(source); + } + }); + INSTANCE.addConverter(String.class, VersionNumber.class, new TypeConverter.Converter() { public VersionNumber convert(String source) @@ -399,6 +408,15 @@ public class DefaultTypeConverter } }); + // From Period + + INSTANCE.addConverter(Period.class, String.class, new TypeConverter.Converter() + { + public String convert(Period source) + { + return source.toString(); + } + }); // // Number to Subtypes and Date diff --git a/source/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java b/source/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java index 333c85d6fa..daa9ecf5bd 100644 --- a/source/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java +++ b/source/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java @@ -39,6 +39,7 @@ import org.alfresco.repo.attributes.MapAttributeValue; import org.alfresco.repo.attributes.StringAttribute; import org.alfresco.repo.attributes.StringAttributeValue; import org.alfresco.service.cmr.repository.MLText; +import org.alfresco.service.cmr.repository.Period; import org.alfresco.util.ISO8601DateFormat; import org.alfresco.util.VersionNumber; @@ -113,6 +114,9 @@ public class DefaultTypeConverterTest extends TestCase assertEquals("fr_FR_", DefaultTypeConverter.INSTANCE.convert(String.class, Locale.FRANCE)); // VersionNumber assertEquals("1.2.3", DefaultTypeConverter.INSTANCE.convert(String.class, new VersionNumber("1.2.3"))); + // Period + assertEquals("period", DefaultTypeConverter.INSTANCE.convert(String.class, new Period("period"))); + assertEquals("period|12", DefaultTypeConverter.INSTANCE.convert(String.class, new Period("period|12"))); } public void testFromString() @@ -148,6 +152,9 @@ public class DefaultTypeConverterTest extends TestCase assertEquals(Locale.FRANCE, DefaultTypeConverter.INSTANCE.convert(Locale.class, "fr_FR_")); assertEquals(new VersionNumber("1.2.3"), DefaultTypeConverter.INSTANCE.convert(VersionNumber.class, "1.2.3")); + + assertEquals(new Period("period"), DefaultTypeConverter.INSTANCE.convert(Period.class, "period")); + assertEquals(new Period("period|12"), DefaultTypeConverter.INSTANCE.convert(Period.class, "period|12")); } String localeStrEn = DefaultTypeConverter.INSTANCE.convert(String.class, Locale.ENGLISH);