it.tidalwave.northernwind.frontend.ui.component.calendar.DefaultCalendarViewController.java Source code

Java tutorial

Introduction

Here is the source code for it.tidalwave.northernwind.frontend.ui.component.calendar.DefaultCalendarViewController.java

Source

/*
 * #%L
 * *********************************************************************************************************************
 *
 * NorthernWind - lightweight CMS
 * http://northernwind.tidalwave.it - git clone https://bitbucket.org/tidalwave/northernwind-src.git
 * %%
 * Copyright (C) 2011 - 2016 Tidalwave s.a.s. (http://tidalwave.it)
 * %%
 * *********************************************************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * *********************************************************************************************************************
 *
 * $Id$
 *
 * *********************************************************************************************************************
 * #L%
 */
package it.tidalwave.northernwind.frontend.ui.component.calendar;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import java.util.Locale;
import java.text.DateFormatSymbols;
import java.time.ZonedDateTime;
import java.io.IOException;
import java.io.StringReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.springframework.beans.factory.annotation.Configurable;
import it.tidalwave.util.NotFoundException;
import it.tidalwave.northernwind.core.model.HttpStatusException;
import it.tidalwave.northernwind.core.model.ResourcePath;
import it.tidalwave.northernwind.core.model.RequestLocaleManager;
import it.tidalwave.northernwind.core.model.ResourceProperties;
import it.tidalwave.northernwind.core.model.Site;
import it.tidalwave.northernwind.core.model.SiteNode;
import it.tidalwave.northernwind.core.model.spi.RequestHolder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import static it.tidalwave.northernwind.frontend.ui.component.Properties.*;

/***********************************************************************************************************************
 *
 * @author  Fabrizio Giudici
 * @version $Id$
 *
 **********************************************************************************************************************/
@RequiredArgsConstructor
@Configurable
@Slf4j
public class DefaultCalendarViewController implements CalendarViewController {
    @Nonnull
    private final CalendarView view;

    @Nonnull
    private final SiteNode siteNode;

    @Nonnull
    private final Site site;

    @Nonnull
    private final RequestLocaleManager requestLocaleManager;

    @Nonnull
    private final RequestHolder requestHolder;

    /*******************************************************************************************************************
     *
     *
     *
     ******************************************************************************************************************/
    @PostConstruct
    /* package */ void initialize() throws NotFoundException, IOException, ParserConfigurationException,
            SAXException, XPathExpressionException, HttpStatusException {
        final String pathParams = requestHolder.get().getPathParams(siteNode);
        final int currentYear = getCurrentYear(pathParams);

        final ResourceProperties siteNodeProperties = siteNode.getProperties();
        final ResourceProperties viewProperties = siteNode.getPropertyGroup(view.getId());

        //        try
        //          {
        //            siteNodeProperties.getProperty(PROPERTY_ENTRIES);
        //          }
        //        catch (NotFoundException e)
        //          {
        //            throw new HttpStatusException(404);
        //          }

        final String entries = siteNodeProperties.getProperty(PROPERTY_ENTRIES);
        final StringBuilder builder = new StringBuilder();
        final int selectedYear = viewProperties.getIntProperty(PROPERTY_SELECTED_YEAR, currentYear);
        final int firstYear = viewProperties.getIntProperty(PROPERTY_FIRST_YEAR,
                Math.min(selectedYear, currentYear));
        final int lastYear = viewProperties.getIntProperty(PROPERTY_LAST_YEAR, Math.max(selectedYear, currentYear));
        final int columns = 4;

        builder.append("<div class='nw-calendar'>\n");
        appendTitle(builder, siteNodeProperties);

        builder.append("<table class='nw-calendar-table'>\n").append("<tbody>\n");

        builder.append(String.format("<tr>%n<th colspan='%d' class='nw-calendar-title'>%d</th>%n</tr>%n", columns,
                selectedYear));

        final String[] monthNames = DateFormatSymbols.getInstance(requestLocaleManager.getLocales().get(0))
                .getMonths();
        final String[] shortMonthNames = DateFormatSymbols.getInstance(Locale.ENGLISH).getShortMonths();

        final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        final DocumentBuilder db = dbf.newDocumentBuilder();
        final Document document = db.parse(new InputSource(new StringReader(entries)));
        final XPathFactory xPathFactory = XPathFactory.newInstance();
        final XPath xPath = xPathFactory.newXPath();

        for (int month = 1; month <= 12; month++) {
            if ((month - 1) % columns == 0) {
                builder.append("<tr>\n");

                for (int column = 0; column < columns; column++) {
                    builder.append(String.format("<th width='%d%%'>%s</th>", 100 / columns,
                            monthNames[month + column - 1]));
                }

                builder.append("</tr>\n<tr>\n");
            }

            builder.append("<td>\n<ul>\n");
            final String pathTemplate = "/calendar/year[@id='%d']/month[@id='%s']/item";
            final String jq1 = String.format(pathTemplate, selectedYear, shortMonthNames[month - 1].toLowerCase());
            final XPathExpression jx1 = xPath.compile(jq1);
            final NodeList nodes = (NodeList) jx1.evaluate(document, XPathConstants.NODESET);

            for (int i = 0; i < nodes.getLength(); i++) {
                // FIXME: verbose XML code below
                final Node node = nodes.item(i);
                final String link = site
                        .createLink(new ResourcePath(node.getAttributes().getNamedItem("link").getNodeValue()));

                String linkClass = "";
                Node typeNode = node.getAttributes().getNamedItem("type");

                if (typeNode != null) {
                    linkClass = String.format(" class='nw-calendar-table-link-%s'", typeNode.getNodeValue());
                }

                final String name = node.getAttributes().getNamedItem("name").getNodeValue();
                builder.append(String.format("<li><a href='%s'%s>%s</a></li>%n", link, linkClass, name));
            }

            builder.append("</ul>\n</td>\n");

            if ((month - 1) % columns == (columns - 1)) {
                builder.append("</tr>\n");
            }
        }

        builder.append("</tbody>\n</table>\n");

        appendYearSelector(builder, firstYear, lastYear, selectedYear);
        builder.append("</div>\n");
        view.setContent(builder.toString());
    }

    /*******************************************************************************************************************
     *
     *
     *
     ******************************************************************************************************************/
    private void appendTitle(final @Nonnull StringBuilder builder,
            final @Nonnull ResourceProperties siteNodeProperties) throws IOException {
        try {
            builder.append(String.format("<h2>%s</h2>%n", siteNodeProperties.getProperty(PROPERTY_TITLE)));
        } catch (NotFoundException e) {
            // ok, no title
        }
    }

    /*******************************************************************************************************************
     *
     *
     *
     ******************************************************************************************************************/
    private void appendYearSelector(final @Nonnull StringBuilder builder, final @Nonnegative int firstYear,
            final @Nonnegative int lastYear, final @Nonnegative int selectedYear) {
        builder.append("<div class='nw-calendar-yearselector'>\n");
        String separator = "";

        for (int year = firstYear; year <= lastYear; year++) {
            builder.append(separator);
            separator = " | ";

            if (year != selectedYear) {
                final String url = site.createLink(siteNode.getRelativeUri().appendedWith("" + year));
                builder.append(String.format("<a href='%s'>%d</a>%n", url, year));
            } else {
                builder.append(year);
            }
        }

        builder.append("</div>\n");
    }

    /*******************************************************************************************************************
     *
     * Returns the current year reading it from the path params, or by default from the calendar.
     *
     ******************************************************************************************************************/
    @Nonnegative
    private int getCurrentYear(final @Nonnull String pathParams) throws HttpStatusException {
        try {
            return "".equals(pathParams) ? ZonedDateTime.now().getYear()
                    : Integer.parseInt(pathParams.replaceAll("/$", "").replaceAll("^/", ""));
            //            return "".equals(pathParams) ? new ZonedDateTime().getYear() : Integer.parseInt(pathParams.replaceAll("/", ""));
        } catch (NumberFormatException e) {
            throw new HttpStatusException(404);
        }
    }
}