Java tutorial
/* * Copyright (c) 2002-2014, Mairie de Paris * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright notice * and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice * and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * License 1.0 */ package fr.paris.lutece.plugins.calendar.service; import fr.paris.lutece.plugins.calendar.business.Agenda; import fr.paris.lutece.plugins.calendar.business.CalendarFilter; import fr.paris.lutece.plugins.calendar.business.CalendarHome; import fr.paris.lutece.plugins.calendar.business.Event; import fr.paris.lutece.plugins.calendar.business.SimpleEvent; import fr.paris.lutece.plugins.calendar.business.category.Category; import fr.paris.lutece.plugins.calendar.service.search.CalendarSearchService; import fr.paris.lutece.plugins.calendar.web.Constants; import fr.paris.lutece.portal.service.content.XPageAppService; import fr.paris.lutece.portal.service.i18n.I18nService; import fr.paris.lutece.portal.service.plugin.Plugin; import fr.paris.lutece.portal.service.plugin.PluginService; import fr.paris.lutece.portal.service.util.AppLogService; import fr.paris.lutece.portal.service.util.AppPathService; import fr.paris.lutece.portal.service.util.AppPropertiesService; import fr.paris.lutece.util.date.DateUtil; import fr.paris.lutece.util.url.UrlItem; import fr.paris.lutece.util.xml.XmlUtil; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.StringReader; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.GregorianCalendar; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.apache.commons.lang.StringUtils; /** * This class provides utils features to manipulate and convert XML calendar * information */ public final class XMLUtils { // CSS Styles public static final String STYLE_CLASS_VIEW_MONTH_DAY = "calendar-view-month-day"; public static final String STYLE_CLASS_VIEW_WEEK_DAY = "calendar-view-week-day"; public static final String STYLE_CLASS_SMALLMONTH_DAY = "calendar-smallmonth-day"; public static final String STYLE_CLASS_SUFFIX_OLD = "-old"; public static final String STYLE_CLASS_SUFFIX_TODAY = "-today"; public static final String STYLE_CLASS_SUFFIX_OFF = "-off"; public static final String STYLE_CLASS_EMPTY_DAY = "calendar-smallmonth-day"; // The names of the XML tags private static final String TAG_EVENTS = "events"; private static final String TAG_AGENDA_EVENT = "event"; private static final String TAG_AGENDA_EVENT_DATE = "event-date"; private static final String TAG_AGENDA_EVENT_LOCATION = "event-location"; private static final String TAG_AGENDA_EVENT_DESCRIPTION = "event-description"; private static final String TAG_AGENDA_EVENT_DATE_TIME_START = "event-date-time-start"; private static final String TAG_AGENDA_EVENT_DATE_TIME_END = "event-date-time-end"; private static final String TAG_AGENDA_EVENT_CATEGORIES = "event-categories"; private static final String TAG_AGENDA_EVENT_STATUS = "event-status"; private static final String TAG_AGENDA_EVENT_SUMMARY = "event-summary"; private static final String TAG_AGENDA_EVENT_URL = "event-url"; private static final String TAG_AGENDA_EVENT_DATE_CREATION = "event-creation-date"; /* Since version 3.0.0 */ private static final String TAG_AGENDA_MONTH = "month"; private static final String TAG_AGENDA_MONTH_LABEL = "month-label"; private static final String TAG_AGENDA_WEEKS = "weeks"; private static final String TAG_AGENDA_WEEK = "week"; private static final String TAG_AGENDA_DAY = "day"; private static final String TAG_AGENDA_DAY_CODE = "day-code"; private static final String TAG_AGENDA_DAY_LABEL = "day-label"; private static final String TAG_WEEK_SHORTCUTS = "week-shortcuts"; private static final String TAG_WEEK_SHORTCUT = "week-shortcut"; private static final String TAG_WEEK_SHORTCUT_LABEL = "week-shortcut-label"; private static final String TAG_WEEK_SHORTCUT_PERIOD = "week-shortcut-period"; private static final String TAG_WEEK_SHORTCUT_DATE_START = "week-shortcut-date-start"; private static final String TAG_WEEK_SHORTCUT_DATE_END = "week-shortcut-date-end"; //PROPERTIES private static final String PROPERTY_SPACE = " "; private static final String PROPERTY_COMMA = ","; private static final String PROPERTY_CALENDAR_RSS_PATTERN = "calendar.rss.format.date"; private static final String PROPERTY_EMPTY_DAY = " "; //Html components private static final String BEGIN_TD_TAG = "<td class="; private static final String END_TD_TAG = "</td>"; private static final String BEGIN_A_TAG = "<a href=\""; private static final String END_A_TAG = "</a>"; private static final String BEGIN_BOLD_TAG = "<b>"; private static final String END_BOLD_TAG = "</b>"; //LOGGER private static final String LOGGER_CALENDAR_EXPORT_XML_CONTENT = "lutece.debug.calendar.export.xmlContent"; /** * Default constructor */ private XMLUtils() { } /** * Returns the Xml code of a calendar events * * @param strAgenda The id of the agenda * @param request request servlet request * @return the Xml code of the agenda content */ public static String getAgendaXml(String strAgenda, HttpServletRequest request) { Agenda agenda = Utils.getAgendaWithOccurrences(strAgenda, request); List<Event> listEvents = agenda.getEvents(); return getXml(listEvents); } /** * Returns the Xml code for RSS * * @param filter The filter * @return the Xml code of the agenda content */ public static String getRssXml(CalendarFilter filter) { List<Event> listEvents = CalendarHome.findEventsByFilter(filter, PluginService.getPlugin(Constants.PLUGIN_NAME)); return getXml(listEvents); } /** * Returns the Xml code of the Calendar portlet without XML heading * * @param listEvents The list of events * @return the Xml code of the agenda content */ public static String getXml(List<Event> listEvents) { if (listEvents != null) { StringBuffer strXml = new StringBuffer(); strXml.append(XmlUtil.getXmlHeader()); // Generate the XML code for the agendas : XmlUtil.beginElement(strXml, TAG_EVENTS); Iterator<Event> i = listEvents.iterator(); while (i.hasNext()) { SimpleEvent event = (SimpleEvent) i.next(); XmlUtil.beginElement(strXml, TAG_AGENDA_EVENT); XmlUtil.addElement(strXml, TAG_AGENDA_EVENT_SUMMARY, (event.getTitle() != null) ? event.getTitle() : ""); String strAddress = event.getLocationAddress(); String strTown = event.getLocationTown(); String strZip = event.getLocationZip(); String strLocation = event.getLocation(); if (strAddress != null) { strLocation += (PROPERTY_SPACE + strAddress); } if (strZip != null) { strLocation += (PROPERTY_SPACE + strZip); } if (strTown != null) { strLocation += (PROPERTY_SPACE + strTown); } UrlItem urlEvent = new UrlItem(AppPathService.getPortalUrl()); urlEvent.addParameter(XPageAppService.PARAM_XPAGE_APP, CalendarPlugin.PLUGIN_NAME); urlEvent.addParameter(Constants.PARAMETER_ACTION, Constants.ACTION_SHOW_RESULT); urlEvent.addParameter(Constants.PARAMETER_EVENT_ID, event.getId()); urlEvent.addParameter(Constants.PARAM_AGENDA, event.getIdCalendar()); String strCreationdate = Constants.EMPTY_STRING; if (event.getDateCreation() != null) { SimpleDateFormat sdf = new SimpleDateFormat( AppPropertiesService.getProperty(PROPERTY_CALENDAR_RSS_PATTERN), Locale.US); strCreationdate = sdf.format(event.getDateCreation()); } XmlUtil.addElement(strXml, TAG_AGENDA_EVENT_LOCATION, (strLocation != null) ? strLocation : ""); XmlUtil.addElement(strXml, TAG_AGENDA_EVENT_DESCRIPTION, (event.getDescription() != null) ? event.getDescription() : ""); if (event.getListCategories() != null) { Collection<Category> listCategories = event.getListCategories(); String strCategories = PROPERTY_SPACE; for (Category category : listCategories) { if (strCategories.equals(PROPERTY_SPACE)) { strCategories = category.getName(); } else { strCategories += (strCategories + PROPERTY_COMMA + category.getName()); } } XmlUtil.addElement(strXml, TAG_AGENDA_EVENT_CATEGORIES, strCategories.trim()); } XmlUtil.addElement(strXml, TAG_AGENDA_EVENT_STATUS, (event.getStatus() != null) ? event.getStatus() : ""); XmlUtil.addElement(strXml, TAG_AGENDA_EVENT_DATE_TIME_START, (event.getDateTimeStart() != null) ? event.getDateTimeStart().replace(":", "") : ""); XmlUtil.addElement(strXml, TAG_AGENDA_EVENT_DATE_TIME_END, (event.getDateTimeEnd() != null) ? event.getDateTimeEnd().replace(":", "") : ""); XmlUtil.addElement(strXml, TAG_AGENDA_EVENT_DATE, Utils.getDate(event.getDate())); XmlUtil.addElementHtml(strXml, TAG_AGENDA_EVENT_URL, urlEvent.getUrl()); XmlUtil.addElement(strXml, TAG_AGENDA_EVENT_DATE_CREATION, strCreationdate); XmlUtil.endElement(strXml, TAG_AGENDA_EVENT); } XmlUtil.endElement(strXml, TAG_EVENTS); if (AppLogService.isDebugEnabled(LOGGER_CALENDAR_EXPORT_XML_CONTENT)) { AppLogService.debug(LOGGER_CALENDAR_EXPORT_XML_CONTENT, strXml.toString()); } return strXml.toString(); } return Constants.EMPTY_STRING; } /** * This method performs XSL Transformation. * * @param strXml The input XML document * @param baSource The source input stream * @param params parameters to apply to the XSL Stylesheet * @param outputProperties properties to use for the xsl transform. Will * overload the xsl output definition. * @return The output document transformed * @throws Exception The exception */ public static byte[] transformXMLToXSL(String strXml, InputStream baSource, Map<String, String> params, Properties outputProperties) throws Exception { Source stylesheet = new StreamSource(baSource); StringReader srInputXml = new StringReader(strXml); StreamSource source = new StreamSource(srInputXml); try { TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(stylesheet); if (outputProperties != null) { transformer.setOutputProperties(outputProperties); } if (params != null) { transformer.clearParameters(); Set<Entry<String, String>> entries = params.entrySet(); for (Entry<String, String> entry : entries) { String name = entry.getKey(); String value = entry.getValue(); transformer.setParameter(name, value); } } ByteArrayOutputStream out = new ByteArrayOutputStream(); Result result = new StreamResult(out); transformer.transform(source, result); return out.toByteArray(); } catch (TransformerConfigurationException e) { String strMessage = e.getMessage(); if (e.getLocationAsString() != null) { strMessage += ("- location : " + e.getLocationAsString()); } throw new Exception("Error transforming document XSLT : " + strMessage, e.getCause()); } catch (TransformerFactoryConfigurationError e) { throw new Exception("Error transforming document XSLT : " + e.getMessage(), e); } catch (TransformerException e) { String strMessage = e.getMessage(); if (e.getLocationAsString() != null) { strMessage += ("- location : " + e.getLocationAsString()); } throw new Exception("Error transforming document XSLT : " + strMessage, e.getCause()); } catch (Exception e) { throw new Exception("Error transforming document XSLT : " + e.getMessage(), e); } } /** * Get the XML of a calendar * @param local The locale * @param cal The calendar * @param request The request * @return The XML */ public static String getXMLPortletCalendar(Locale local, Calendar cal, HttpServletRequest request) { StringBuffer strXml = new StringBuffer(); String strDay = null; Calendar calendar = new GregorianCalendar(); //Set the calendar in the beginning of the month calendar.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 1); int nDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); //If day of week is sunday: nDayOfWeek = 8 if (nDayOfWeek == 1) { nDayOfWeek = 8; } Calendar calendar2 = new GregorianCalendar(); calendar2.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), calendar.getMaximum(Calendar.DAY_OF_MONTH)); //Beginning of the main xml block: month XmlUtil.beginElement(strXml, TAG_AGENDA_MONTH); String strBaseUrl = AppPathService.getPortalUrl(); UrlItem urlMonth = new UrlItem(strBaseUrl); urlMonth.addParameter(Constants.PARAMETER_PAGE, Constants.PLUGIN_NAME); urlMonth.addParameter(Constants.PARAMETER_ACTION, Constants.ACTION_DO_SEARCH); urlMonth.addParameter(Constants.PARAMETER_DATE_START, DateUtil.getDateString(calendar.getTime(), local)); urlMonth.addParameter(Constants.PARAMETER_DATE_END, DateUtil.getDateString(calendar2.getTime(), local)); urlMonth.addParameter(Constants.PARAMETER_PERIOD, Constants.PROPERTY_PERIOD_RANGE); String strMonthLabel = Utils.getMonthLabel(Utils.getDate(calendar), local); String strUrlMonth = BEGIN_A_TAG + urlMonth.getUrl() + "\">" + strMonthLabel + END_A_TAG; XmlUtil.addElementHtml(strXml, TAG_AGENDA_MONTH_LABEL, strUrlMonth); //Shortcut tags //Begenning of the xml block: week-shortcuts XmlUtil.beginElement(strXml, TAG_WEEK_SHORTCUTS); //Today shortcut XmlUtil.beginElement(strXml, TAG_WEEK_SHORTCUT); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTCUT_TODAY, local)); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_PERIOD, Constants.PROPERTY_PERIOD_TODAY); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_DATE_START, DateUtil.getDateString(new Date(), local)); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_DATE_END, DateUtil.getDateString(new Date(), local)); XmlUtil.endElement(strXml, TAG_WEEK_SHORTCUT); //Tomorrow shortcut Calendar calTomorrow = new GregorianCalendar(); calTomorrow.add(Calendar.DATE, 1); XmlUtil.beginElement(strXml, TAG_WEEK_SHORTCUT); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTCUT_TOMORROW, local)); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_PERIOD, Constants.PROPERTY_PERIOD_RANGE); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_DATE_START, DateUtil.getDateString(calTomorrow.getTime(), local)); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_DATE_END, DateUtil.getDateString(calTomorrow.getTime(), local)); XmlUtil.endElement(strXml, TAG_WEEK_SHORTCUT); //Week shortcut Date dateBeginWeek = null; Date dateEndWeek = null; Calendar calendarToday = new GregorianCalendar(); Calendar calendarFirstDay = Calendar.getInstance(); Calendar calendarLastDay = new GregorianCalendar(); calendarFirstDay = calendarToday; calendarFirstDay.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); calendarLastDay = (GregorianCalendar) calendarFirstDay.clone(); calendarLastDay.add(Calendar.DATE, 6); dateBeginWeek = calendarFirstDay.getTime(); dateEndWeek = calendarLastDay.getTime(); XmlUtil.beginElement(strXml, TAG_WEEK_SHORTCUT); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTCUT_WEEK, local)); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_PERIOD, Constants.PROPERTY_PERIOD_WEEK); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_DATE_START, DateUtil.getDateString(dateBeginWeek, local)); XmlUtil.addElement(strXml, TAG_WEEK_SHORTCUT_DATE_END, DateUtil.getDateString(dateEndWeek, local)); XmlUtil.endElement(strXml, TAG_WEEK_SHORTCUT); //Ending of the xml block: week-shortcuts XmlUtil.endElement(strXml, TAG_WEEK_SHORTCUTS); //Begenning of the xml block: weeks XmlUtil.beginElement(strXml, TAG_AGENDA_WEEKS); //Day label tags XmlUtil.addElement(strXml, TAG_AGENDA_DAY_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTLABEL_MONDAY, local)); XmlUtil.addElement(strXml, TAG_AGENDA_DAY_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTLABEL_TUESDAY, local)); XmlUtil.addElement(strXml, TAG_AGENDA_DAY_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTLABEL_WEDNESDAY, local)); XmlUtil.addElement(strXml, TAG_AGENDA_DAY_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTLABEL_THURSDAY, local)); XmlUtil.addElement(strXml, TAG_AGENDA_DAY_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTLABEL_FRIDAY, local)); XmlUtil.addElement(strXml, TAG_AGENDA_DAY_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTLABEL_SATURDAY, local)); XmlUtil.addElement(strXml, TAG_AGENDA_DAY_LABEL, I18nService.getLocalizedString(Constants.PROPERTY_SHORTLABEL_SUNDAY, local)); //Check if the month is ended boolean bDone = false; //check if the month is started boolean bStarted = false; //While the month isn't over... while (!bDone) { //Begenning of the xml block: week XmlUtil.beginElement(strXml, TAG_AGENDA_WEEK); for (int i = 0; i < 7; i++) { if ((((i + 2) != nDayOfWeek) && !bStarted) || bDone) { XmlUtil.beginElement(strXml, TAG_AGENDA_DAY); strDay = BEGIN_TD_TAG + getDayClass(calendar) + ">" + PROPERTY_EMPTY_DAY + END_TD_TAG; XmlUtil.addElementHtml(strXml, TAG_AGENDA_DAY_CODE, strDay); XmlUtil.endElement(strXml, TAG_AGENDA_DAY); continue; } bStarted = true; //put parameters in the url UrlItem urlDay = new UrlItem(strBaseUrl); String strPageId = request != null ? request.getParameter(Constants.PARAMETER_PAGE_ID) : StringUtils.EMPTY; if (StringUtils.isNotBlank(strPageId) && StringUtils.isNumeric(strPageId)) { urlDay.addParameter(Constants.PARAMETER_PAGE_ID, strPageId); } urlDay.addParameter(Constants.PARAMETER_DATE, DateUtil.getDateString(calendar.getTime(), local)); //construct on url based on day String strUrlDay = new String(); strUrlDay = BEGIN_A_TAG + urlDay.getUrl() + "\">" + Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)) + END_A_TAG; XmlUtil.beginElement(strXml, TAG_AGENDA_DAY); Date date = Utils.getDate(Utils.getDate(calendar)); Plugin plugin = PluginService.getPlugin(CalendarPlugin.PLUGIN_NAME); String[] arrayCalendarIds = Utils.getCalendarIds(request); List<Event> listEvent = CalendarSearchService.getInstance().getSearchResults(arrayCalendarIds, null, "", date, date, plugin); if (listEvent.size() != 0) { strDay = BEGIN_TD_TAG + Constants.STYLE_CLASS_SMALLMONTH_DAY + Constants.STYLE_CLASS_SUFFIX_EVENT + ">" + BEGIN_BOLD_TAG + strUrlDay + END_BOLD_TAG + END_TD_TAG; } else { strDay = BEGIN_TD_TAG + getDayClass(calendar) + ">" + Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)) + END_TD_TAG; } XmlUtil.addElementHtml(strXml, TAG_AGENDA_DAY_CODE, strDay); XmlUtil.endElement(strXml, TAG_AGENDA_DAY); int nDay = calendar.get(Calendar.DAY_OF_MONTH); calendar.roll(Calendar.DAY_OF_MONTH, true); int nNewDay = calendar.get(Calendar.DAY_OF_MONTH); if (nNewDay < nDay) { bDone = true; } } //Ending of the xml block: week XmlUtil.endElement(strXml, TAG_AGENDA_WEEK); } //Ending of the xml block: weeks XmlUtil.endElement(strXml, TAG_AGENDA_WEEKS); //Ending of the xml block: month XmlUtil.endElement(strXml, TAG_AGENDA_MONTH); return strXml.toString(); } /** * Calculate the style class to render the day * @param calendar A calendar object positionned on the day to render * @return A CSS style */ private static String getDayClass(Calendar calendar) { StringBuilder sbClass = new StringBuilder(Constants.STYLE_CLASS_SMALLMONTH_DAY); String strDate = Utils.getDate(calendar); String strToday = Utils.getDateToday(); if (Utils.isDayOff(calendar)) { sbClass.append(Constants.STYLE_CLASS_SUFFIX_OFF); } else if (strDate.compareTo(strToday) < 0) { sbClass.append(Constants.STYLE_CLASS_SUFFIX_OLD); } else if (strDate.equals(strToday)) { sbClass.append(Constants.STYLE_CLASS_SUFFIX_TODAY); } return sbClass.toString(); } }