001/* 002 * Copyright 2012 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.calendar.events; 017 018import org.apache.avalon.framework.logger.LogEnabled; 019import org.apache.avalon.framework.logger.Logger; 020import org.apache.avalon.framework.service.ServiceException; 021import org.apache.avalon.framework.service.ServiceManager; 022import org.apache.avalon.framework.service.Serviceable; 023import org.apache.commons.lang.StringUtils; 024import org.joda.time.DateTime; 025import org.joda.time.Interval; 026import org.joda.time.format.ISODateTimeFormat; 027 028import org.ametys.cms.contenttype.ContentType; 029import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 030import org.ametys.cms.contenttype.MetadataDefinition; 031import org.ametys.cms.contenttype.MetadataType; 032import org.ametys.cms.repository.Content; 033import org.ametys.plugins.repository.AmetysObjectResolver; 034import org.ametys.runtime.parameter.ParameterHelper; 035import org.ametys.runtime.parameter.ParameterHelper.ParameterType; 036 037/** 038 * Helper class that provides a method to check if a date is between two others. 039 */ 040public final class EventHelper implements LogEnabled, Serviceable 041{ 042 /** The Ametys object resolver */ 043 protected static AmetysObjectResolver _resolver; 044 /** The extension point for content types */ 045 protected static ContentTypeExtensionPoint _contentTypeEP; 046 047 private static Logger _logger; 048 049 @Override 050 public void enableLogging(Logger logger) 051 { 052 _logger = logger; 053 } 054 055 @Override 056 public void service(ServiceManager manager) throws ServiceException 057 { 058 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 059 _contentTypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 060 } 061 062 /** 063 * Tests if the given date is either: 064 * - equal to the first, if there is no end date. 065 * - between the two dates, if there is a start and end date. 066 * @param dateStr the date to test. 067 * @param startStr start of the interval. 068 * @param endStr end of the interval. 069 * @return true if the date is either equal to the start date or between the start and end date. 070 */ 071 public static boolean isBetween(String dateStr, String startStr, String endStr) 072 { 073 boolean between = false; 074 075 DateTime date = ISODateTimeFormat.date().parseDateTime(dateStr); 076 DateTime start = ISODateTimeFormat.date().parseDateTime(startStr); 077 078 if (StringUtils.isBlank(endStr)) 079 { 080 between = date.equals(start); 081 } 082 else 083 { 084 DateTime end = ISODateTimeFormat.date().parseDateTime(endStr); 085 between = (date.isAfter(start) || date.equals(start)) && (date.isBefore(end) || date.equals(end)); 086 } 087 088 return between; 089 } 090 091 /** 092 * Tests if the given event occurs in the given month. 093 * @param monthStartStr The month first day, cannot be null or blank. 094 * @param eventStartStr The event start date, can be null or blank only if the end date is set. 095 * @param eventEndStr The event end date, can be null or blank only if the end date is set. 096 * @return true if the event occurs in the given month. 097 */ 098 public static boolean inMonth(String monthStartStr, String eventStartStr, String eventEndStr) 099 { 100 boolean overlaps = false; 101 102 DateTime monthStart = new DateTime(ParameterHelper.castValue(monthStartStr, ParameterType.DATE)); 103 DateTime monthEnd = monthStart.withDayOfMonth(1).withMillisOfDay(0).plusMonths(1); 104 Interval month = new Interval(monthStart, monthEnd); 105 106 if (StringUtils.isNotBlank(eventStartStr) && StringUtils.isNotBlank(eventEndStr)) 107 { 108 DateTime eventStart = new DateTime(ParameterHelper.castValue(eventStartStr, ParameterType.DATE)); 109 DateTime eventEnd = new DateTime(ParameterHelper.castValue(eventEndStr, ParameterType.DATE)); 110 111 // check that start is before end to avoid an unwanted exception 112 try 113 { 114 // If eventStart equals to eventEnd and equals to monthStart, month#overlaps(Interval) will return false. In our case, we want to consider it actually does. 115 overlaps = eventStartStr.equals(eventEndStr) ? month.contains(eventStart) 116 : month.overlaps(new Interval(eventStart, eventEnd)); 117 } 118 catch (IllegalArgumentException e) 119 { 120 // The end is before the start 121 overlaps = false; 122 _logger.error(String.format("Invalid dates of event: the end date (%s) must be greater or equal to the start date (%s). The event will be ignored in calendar view.", eventEndStr, eventStartStr), e); 123 } 124 } 125 else if (StringUtils.isNotBlank(eventStartStr)) 126 { 127 DateTime date = new DateTime(ParameterHelper.castValue(eventStartStr, ParameterType.DATE)); 128 overlaps = month.contains(date); 129 } 130 else if (StringUtils.isNotBlank(eventEndStr)) 131 { 132 DateTime date = new DateTime(ParameterHelper.castValue(eventEndStr, ParameterType.DATE)); 133 overlaps = month.contains(date); 134 } 135 136 return overlaps; 137 } 138 139 /** 140 * Tests if the given date is either: 141 * @param dateStr the date to test. 142 * @return true if the date is either equal to the start date or between the start and end date. 143 */ 144 public static String nextDay(String dateStr) 145 { 146 DateTime date = ISODateTimeFormat.dateTime().parseDateTime(dateStr); 147 148 return ISODateTimeFormat.dateTime().print(date.plusDays(1)); 149 } 150 151 /** 152 * Tests if the given date is either: 153 * @param dateStr the date to test. 154 * @param format the format ("date" or "basicDate"). 155 * @return true if the date is either equal to the start date or between the start and end date. 156 */ 157 public static String nextDay(String dateStr, String format) 158 { 159 String nextDayStr = ""; 160 161 DateTime date = ISODateTimeFormat.dateTime().parseDateTime(dateStr); 162 163 DateTime nextDay = date.plusDays(1); 164 165 if ("basicDate".equals(format)) 166 { 167 nextDayStr = ISODateTimeFormat.basicDate().print(nextDay); 168 } 169 else 170 { 171 nextDayStr = ISODateTimeFormat.date().print(nextDay); 172 } 173 174 return nextDayStr; 175 } 176 177 /** 178 * Tests if the given metadata for the given content is of type {@link MetadataType#DATETIME} 179 * @param contentId The id of the content 180 * @param metadataName The metadata name 181 * @return true if the given metadata for the given content is of type {@link MetadataType#DATETIME} 182 */ 183 public static boolean isDatetime(String contentId, String metadataName) 184 { 185 Content content = _resolver.resolveById(contentId); 186 String[] cTypes = content.getTypes(); 187 188 for (String cTypeId : cTypes) 189 { 190 ContentType cType = _contentTypeEP.getExtension(cTypeId); 191 192 if (cType.hasMetadataDefinition(metadataName)) 193 { 194 MetadataDefinition metadataDef = cType.getMetadataDefinition(metadataName); 195 MetadataType type = metadataDef.getType(); 196 197 return MetadataType.DATETIME.equals(type); 198 } 199 } 200 201 return false; 202 } 203}