org.exoplatform.wiki.rendering.macro.update.RecentlyUpdatedMacro.java Source code

Java tutorial

Introduction

Here is the source code for org.exoplatform.wiki.rendering.macro.update.RecentlyUpdatedMacro.java

Source

/*
 * Copyright (C) 2003-2013 eXo Platform SAS.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.exoplatform.wiki.rendering.macro.update;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.inject.Inject;

import org.apache.commons.lang.StringUtils;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.wiki.mow.api.Wiki;
import org.exoplatform.wiki.mow.api.WikiNodeType;
import org.exoplatform.wiki.mow.core.api.wiki.PageImpl;
import org.exoplatform.wiki.rendering.builder.ReferenceBuilder;
import org.exoplatform.wiki.rendering.context.MarkupContextManager;
import org.exoplatform.wiki.service.WikiContext;
import org.exoplatform.wiki.service.WikiPageParams;
import org.exoplatform.wiki.service.WikiService;
import org.exoplatform.wiki.service.search.SearchResult;
import org.exoplatform.wiki.service.search.WikiSearchData;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;
import org.xwiki.rendering.block.Block;
import org.xwiki.rendering.block.BulletedListBlock;
import org.xwiki.rendering.block.GroupBlock;
import org.xwiki.rendering.block.LinkBlock;
import org.xwiki.rendering.block.ListItemBlock;
import org.xwiki.rendering.block.SpaceBlock;
import org.xwiki.rendering.block.WordBlock;
import org.xwiki.rendering.listener.reference.DocumentResourceReference;
import org.xwiki.rendering.listener.reference.ResourceType;
import org.xwiki.rendering.macro.AbstractMacro;
import org.xwiki.rendering.macro.MacroExecutionException;
import org.xwiki.rendering.transformation.MacroTransformationContext;

/**
 * Created by The eXo Platform SAS
 * Author : eXoPlatform
 *          exo@exoplatform.com
 * Jul 22, 2013  
 */
@Component("recentlyupdated")
public class RecentlyUpdatedMacro extends AbstractMacro<RecentlyUpdatedMacroParameters> {

    private static final String NAME = "RecentlyUpdated";
    private static final String DESCRIPTION = "Lists wiki pages which were updated recently";

    private static final Log LOG = ExoLogger.getLogger(RecentlyUpdatedMacro.class.getName());

    @Inject
    private ComponentManager componentManager;

    @Inject
    private Execution execution;

    @Inject
    private MarkupContextManager markupContextManager;

    public RecentlyUpdatedMacro() {
        super(NAME, DESCRIPTION, RecentlyUpdatedMacroParameters.class);
    }

    @Override
    public List<Block> execute(RecentlyUpdatedMacroParameters parameters, String content,
            MacroTransformationContext context) throws MacroExecutionException {

        List<SearchResult> results = searchRecentlyUpdatedWikiPages(parameters);
        Block group = new GroupBlock();
        Block childrenBlock = new BulletedListBlock(Collections.<Block>emptyList());
        for (SearchResult res : results) {
            try {
                Block itemBlock = transformToBlock(res, context);
                childrenBlock.addChild(itemBlock);
            } catch (Exception e) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Can not build result: " + res.getPath(), e);
                }
            }
        }
        group.addChild(childrenBlock);
        return Collections.singletonList((Block) group);
    }

    private List<SearchResult> searchRecentlyUpdatedWikiPages(RecentlyUpdatedMacroParameters params)
            throws MacroExecutionException {
        WikiPageParams pageParams = getWikiContext();
        //set constraints
        //wiki 
        WikiSearchData data = new WikiSearchData(null, null, pageParams.getType(), pageParams.getOwner());
        setWiki(data, params);
        //authors
        data.addPropertyConstraint(getAuthorConstraints(params.getAuthors()));
        //last modified date
        data.addPropertyConstraint(getTimeConstraint(params.getTime()));
        //contents
        data.setContent("*");
        //limit
        data.setLimit(getEntries(params.getEntries()));
        //search
        data.setSort("exo:lastModifiedDate");
        data.setOrder("DESC");
        WikiService wikiService = (WikiService) PortalContainer.getComponent(WikiService.class);
        try {
            return wikiService.search(data).getAll();
        } catch (Exception e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Can not search recently updated wiki pages", e);
            }
            return new ArrayList<SearchResult>();
        }
    }

    private void setWiki(WikiSearchData data, RecentlyUpdatedMacroParameters params) {
        String wikiSt = params.getWikis();
        if (StringUtils.isNotBlank(wikiSt)) {
            WikiService wikiService = (WikiService) PortalContainer.getComponent(WikiService.class);
            if (!wikiSt.startsWith("/")) {
                wikiSt = "/" + wikiSt;
            }
            Wiki wiki = wikiService.getWikiById(params.getWikis());
            if (wiki != null) {
                data.setWikiType(wiki.getType());
                data.setWikiOwner(wiki.getOwner());
            }
        }
    }

    private String getAuthorConstraints(String authorList) {
        StringBuffer authorConstraint = new StringBuffer();
        authorConstraint.append(" AND ( ");
        if (StringUtils.isBlank(authorList)) {
            authorConstraint.append(WikiNodeType.Definition.EXO_LAST_MODIFIER).append(" IS NOT NULL");
        } else {
            int count = 0;
            for (String author : authorList.split(",")) {
                if (count++ > 0) {
                    authorConstraint.append(" OR ");
                }
                authorConstraint.append(" ( ").append(WikiNodeType.Definition.EXO_LAST_MODIFIER).append("='")
                        .append(author).append("' )");
            }
        }
        authorConstraint.append(" ) ");
        return authorConstraint.toString();
    }

    private String getTimeConstraint(String time) throws MacroExecutionException {
        StringBuffer timeConstraint = new StringBuffer();
        Calendar date = new GregorianCalendar();
        if (StringUtils.isNotBlank(time)) {
            timeConstraint.append(" AND ( ");
            String pattern = "((\\d)+d)?((\\d)+h)?((\\d)+m)?((\\d)+s)?";
            if (time.matches(pattern)) {
                //get time value
                int day = getValue(time, "(\\d)+d");
                int hour = getValue(time, "(\\d)+h");
                int minute = getValue(time, "(\\d)+m");
                int second = getValue(time, "(\\d)+s");
                date.add(Calendar.DATE, (-1) * day);
                date.add(Calendar.HOUR, (-1) * hour);
                date.add(Calendar.MINUTE, (-1) * minute);
                date.add(Calendar.SECOND, (-1) * second);
                //append constraint
                SimpleDateFormat formatDateTime = new SimpleDateFormat();
                formatDateTime.applyPattern("YYYY-MM-DDThh:mm:ss.sTZD");
                String calculatedTime = formatDateTime.format(date.getTime()) + "T00:00:00.000";
                timeConstraint.append(WikiNodeType.Definition.EXO_LAST_MODIFIED_DATE).append(" >= TIMESTAMP '")
                        .append(calculatedTime).append("'");
            } else {
                throw new MacroExecutionException(
                        String.format("Time is not correct: %s, please use pattern d h m s", time));
            }
            timeConstraint.append(" ) ");
        }
        return timeConstraint.toString();
    }

    private int getValue(String st, String pattern) {
        Pattern pt = Pattern.compile(pattern);
        Matcher matcher = pt.matcher(st);
        if (!matcher.find()) {
            return 0;
        }
        String value = matcher.group();
        return Integer.parseInt(value.substring(0, value.length() - 1));
    }

    private int getEntries(String entries) throws MacroExecutionException {
        if (StringUtils.isBlank(entries)) {
            return 10;
        }
        try {
            return Integer.parseInt(entries);
        } catch (NumberFormatException e) {
            throw new MacroExecutionException("entries value is incorrect", e);
        }
    }

    private WikiContext getWikiContext() {
        ExecutionContext ec = execution.getContext();
        if (ec != null) {
            WikiContext wikiContext = (WikiContext) ec.getProperty(WikiContext.WIKICONTEXT);
            return wikiContext;
        }
        return null;
    }

    private ListItemBlock transformToBlock(SearchResult res, MacroTransformationContext context) throws Exception {
        List<Block> blocks = new ArrayList<Block>();
        String pageName = res.getPageName();
        if (pageName.indexOf("/") >= 0) {
            pageName = pageName.substring(pageName.lastIndexOf("/") + 1);
        }
        WikiPageParams params = markupContextManager.getMarkupContext(pageName, ResourceType.DOCUMENT);
        DocumentResourceReference link = new DocumentResourceReference(getReferenceBuilder(context).build(params));
        //link to wiki page
        List<Block> content = new ArrayList<Block>();
        content.add(new WordBlock(res.getTitle()));
        LinkBlock linkBlock = new LinkBlock(content, link, true);
        blocks.add(linkBlock);
        //created by or updated by
        blocks.add(new SpaceBlock());
        WikiService wikiService = (WikiService) ExoContainerContext.getCurrentContainer()
                .getComponentInstanceOfType(WikiService.class);
        PageImpl page = (PageImpl) wikiService.getPageById(params.getType(), params.getOwner(), params.getPageId());
        String modifyText = page.getCreatedDate().equals(page.getUpdatedDate()) ? "created by " : " updated by";
        blocks.add(new WordBlock(modifyText));
        //user name
        blocks.add(new SpaceBlock());
        blocks.add(new WordBlock(page.getAuthor()));
        //time
        blocks.add(new SpaceBlock());
        SimpleDateFormat formatDateTime = new SimpleDateFormat();
        formatDateTime.applyPattern("yyyy.MMMM.dd GGG hh:mm aaa");
        blocks.add(new WordBlock(formatDateTime.format(
                page.getJCRPageNode().getProperty(WikiNodeType.Definition.UPDATED_DATE).getDate().getTime())));

        return new ListItemBlock(blocks);
    }

    private ReferenceBuilder getReferenceBuilder(MacroTransformationContext context)
            throws MacroExecutionException {
        try {
            return componentManager.getInstance(ReferenceBuilder.class, context.getSyntax().toIdString());
        } catch (ComponentLookupException e) {
            throw new MacroExecutionException(String.format("Failed to find reference builder for syntax %s",
                    context.getSyntax().toIdString()), e);
        }
    }

    @Override
    public boolean supportsInlineMode() {
        return true;
    }
}