Package org.fao.geonet.kernel.metadata

Source Code of org.fao.geonet.kernel.metadata.DefaultStatusActions

//=============================================================================
//===  Copyright (C) 2001-2011 Food and Agriculture Organization of the
//===  United Nations (FAO-UN), United Nations World Food Programme (WFP)
//===  and United Nations Environment Programme (UNEP)
//===
//===  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 St, Fifth Floor, Boston, MA 02110-1301, USA
//===
//===  Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
//===  Rome - Italy. email: geonetwork@osgeo.org
//==============================================================================

package org.fao.geonet.kernel.metadata;

import com.google.common.base.Function;
import com.google.common.collect.Lists;

import jeeves.server.UserSession;
import jeeves.server.context.ServiceContext;

import org.fao.geonet.GeonetContext;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.constants.Params;
import org.fao.geonet.domain.*;
import org.fao.geonet.kernel.DataManager;
import org.fao.geonet.kernel.setting.SettingManager;
import org.fao.geonet.repository.MetadataRepository;
import org.fao.geonet.repository.SortUtils;
import org.fao.geonet.repository.StatusValueRepository;
import org.fao.geonet.repository.UserRepository;
import org.fao.geonet.util.LangUtils;
import org.fao.geonet.util.MailSender;
import org.fao.geonet.util.XslUtil;
import org.jdom.JDOMException;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DefaultStatusActions implements StatusActions {

    private String host, port, username, password, from, fromDescr, replyTo, replyToDescr;
    private boolean useSSL;    protected ServiceContext context;
    protected String language;
    protected DataManager dm;
    protected String siteUrl;
    protected String siteName;
    protected UserSession session;
    protected boolean emailNotes = true;
    private StatusValueRepository _statusValueRepository;

    /**
     * Constructor.
     */
    public DefaultStatusActions() {
    }

    /**
     * Initializes the StatusActions class with external info from GeoNetwork.
     *
     *
     * @param context
     * @throws IOException
     * @throws JDOMException
     */
    public void init(ServiceContext context) throws Exception {

        this.context = context;
        this._statusValueRepository = context.getBean(StatusValueRepository.class);
        this.language = context.getLanguage();

        GeonetContext gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME);
        SettingManager sm = gc.getBean(SettingManager.class);

        siteName = sm.getSiteName();
        host = sm.getValue("system/feedback/mailServer/host");
        port = sm.getValue("system/feedback/mailServer/port");
        from = sm.getValue("system/feedback/email");
        username = sm.getValue("system/feedback/mailServer/username");
        password = sm.getValue("system/feedback/mailServer/password");
        useSSL = sm.getValueAsBool("system/feedback/mailServer/ssl");
       
        if (host == null || host.length() == 0) {
            context.error("Mail server host not configure");
            emailNotes = false;
        }

        if (port == null || port.length() == 0) {
            context.error("Mail server port not configured, email notifications won't be sent.");
            emailNotes = false;
        }

        if (from == null || from.length() == 0) {
            context.error("Mail feedback address not configured, email notifications won't be sent.");
            emailNotes = false;
        }

        fromDescr = siteName + LangUtils.translate(context, "statusTitle").get(this.language);

        session = context.getUserSession();
        replyTo = session.getEmailAddr();
        if (replyTo != null) {
            replyToDescr = session.getName() + " " + session.getSurname();
        } else {
            replyTo = from;
            replyToDescr = fromDescr;
        }

        dm = gc.getBean(DataManager.class);
        siteUrl = context.getBean(SettingManager.class).getSiteURL(context);
    }

    /**
     * Called when a record is edited to set/reset status.
     *
     * @param id The metadata id that has been edited.
     * @param minorEdit If true then the edit was a minor edit.
     */
    public void onEdit(int id, boolean minorEdit) throws Exception {

        if (!minorEdit && dm.getCurrentStatus(id).equals(Params.Status.APPROVED)) {
            String changeMessage = String.format(LangUtils.translate(context, "statusUserEdit").get(this.language), replyToDescr,
                    replyTo, id);
            unsetAllOperations(id);
            dm.setStatus(context, id, Integer.valueOf(Params.Status.DRAFT), new ISODate(), changeMessage);
        }

    }

    /**
     * Called when need to set status on a set of metadata records.
     *
     * @param status The status to set.
     * @param metadataIds The set of metadata ids to set status on.
     * @param changeDate The date the status was changed.
     * @param changeMessage The message explaining why the status has changed.
     */
    public Set<Integer> statusChange(String status, Set<Integer> metadataIds, ISODate changeDate, String changeMessage) throws Exception {

        Set<Integer> unchanged = new HashSet<Integer>();

        // -- process the metadata records to set status
        for (Integer mid : metadataIds) {
            String currentStatus = dm.getCurrentStatus(mid);

            // --- if the status is already set to value of status then do nothing
            if (status.equals(currentStatus)) {
                if (context.isDebugEnabled())
                    context.debug("Metadata " + mid + " already has status " + mid);
                unchanged.add(mid);
            }

            if (status.equals(Params.Status.APPROVED)) {
                // setAllOperations(mid); - this is a short cut that could be enabled
            } else if (status.equals(Params.Status.DRAFT) || status.equals(Params.Status.REJECTED)) {
                unsetAllOperations(mid);
            }

            // --- set status, indexing is assumed to take place later
            dm.setStatusExt(context, mid, Integer.valueOf(status), changeDate, changeMessage);
        }

        // --- inform content reviewers if the status is submitted
        if (status.equals(Params.Status.SUBMITTED)) {
            informContentReviewers(metadataIds, changeDate.toString(), changeMessage);
            // --- inform owners if status is approved
        } else if (status.equals(Params.Status.APPROVED) || status.equals(Params.Status.REJECTED)) {
            informOwners(metadataIds, changeDate.toString(), changeMessage, status);
        }

        return unchanged;
    }

    // -------------------------------------------------------------------------
    // Private methods
    // -------------------------------------------------------------------------

  /**
    * Unset all operations on 'All' Group. Used when status changes from approved to something else.
    *
    * @param mdId The metadata id to unset privileges on
    */
  private void unsetAllOperations(int mdId) throws Exception {
      String allGroup = "1";
      for (ReservedOperation op : ReservedOperation.values()) {
          dm.unsetOperation(context, mdId+"", allGroup, op);
      }
  }

    /**
     * Inform content reviewers of metadata records in list that they need to review the record.
     *
     * @param metadata The selected set of metadata records
     * @param changeDate The date that of the change in status
     * @param changeMessage Message supplied by the user that set the status
     */
    protected void informContentReviewers(Set<Integer> metadata, String changeDate, String changeMessage) throws Exception {

        // --- get content reviewers (sorted on content reviewer userid)
        UserRepository userRepository = context.getBean(UserRepository.class);
        List<Pair<Integer, User>> results = userRepository.findAllByGroupOwnerNameAndProfile(metadata,
                Profile.Reviewer, SortUtils.createSort(User_.name));

        List<User> users = Lists.transform(results, new Function<Pair<Integer, User>, User>() {
            @Nullable
            @Override
            public User apply(@Nonnull Pair<Integer, User> input) {
                    return input.two();
            }
        });
        String mdChanged = buildMetadataChangedMessage(metadata);
        String translatedStatusName = getTranslatedStatusName(Params.Status.SUBMITTED);
        String subject = String.format(LangUtils.translate(context, "statusInform").get(this.language), siteName,
                translatedStatusName, replyToDescr, replyTo, changeDate);

        processList(users, subject, Params.Status.SUBMITTED,
                changeDate, changeMessage, mdChanged);
    }

    public static final Pattern metadataLuceneField = Pattern.compile("\\{\\{index:([^\\}]+)\\}\\}");
   
    private String buildMetadataChangedMessage(Set<Integer> metadata) {
      String statusMetadataDetails = null;
      String message = "";
      try {
        statusMetadataDetails = LangUtils.translate(context, "statusMetadataDetails").get(this.language);
    } catch (Exception e) {}
      // Fallback on a default value if statusMetadataDetails not resolved
      if (statusMetadataDetails == null) {
        statusMetadataDetails = "* {{index:title}} ({{serverurl}}/search?uuid={{index:_uuid}})";
      }
     
      ArrayList<String> fields = new ArrayList<String>();
     
      Matcher m = metadataLuceneField.matcher(statusMetadataDetails);
        Iterable<Metadata> mds = this.context.getBean(MetadataRepository.class).findAll(metadata);
       
      while (m.find()) {
        fields.add(m.group(1));
      }
     
      for (Metadata md : mds) {
        String curMdDetails = statusMetadataDetails;
        // First substitution for variables not stored in the index
        curMdDetails = curMdDetails.replace("{{serverurl}}", siteUrl);
       
        for (String f: fields) {
          String mdf = XslUtil.getIndexField(null, md.getUuid(), f, this.language);
          curMdDetails = curMdDetails.replace("{{index:" + f + "}}", mdf);
        }
        message = message.concat(curMdDetails + "\r\n");
      }
    return message;
  }

  private String getTranslatedStatusName(String statusValueId) {
        String translatedStatusName = "";
        StatusValue s = _statusValueRepository.findOneById(Integer.valueOf(statusValueId));
        if (s == null) {
            translatedStatusName = statusValueId;
        } else {
          translatedStatusName = s.getLabel(this.language);
        }
        return translatedStatusName;
    }

    /**
     * Inform owners of metadata records that the records have approved or rejected.
     *
     * @param metadataIds The selected set of metadata records
     * @param changeDate The date that of the change in status
     * @param changeMessage Message supplied by the user that set the status
     */
    protected void informOwners(Set<Integer> metadataIds, String changeDate, String changeMessage, String status)
            throws Exception {

        String translatedStatusName = getTranslatedStatusName(status);
        // --- get metadata owners (sorted on owner userid)
        String subject = String.format(LangUtils.translate(context, "statusInform").get(this.language), siteName,
                translatedStatusName, replyToDescr, replyTo, changeDate);
        String mdChanged = buildMetadataChangedMessage(metadataIds);
       
        Iterable<Metadata> metadata = this.context.getBean(MetadataRepository.class).findAll(metadataIds);
        List<User> owners = new ArrayList<User>();
        UserRepository userRepo = this.context.getBean(UserRepository.class);

        for (Metadata md : metadata) {
            int ownerId = md.getSourceInfo().getOwner();
            owners.add(userRepo.findOne(ownerId));
        }

        processList(owners, subject, status, changeDate, changeMessage, mdChanged);

    }

    /**
     * Process the users and metadata records for emailing notices.
     *
     * @param users The selected set of users
     * @param subject Subject to be used for email notices
     * @param status The status being set
     * @param changeDate Datestamp of status change
     * @param changeMessage The message indicating why the status has changed
     */
    protected void processList(List<User> users, String subject, String status, String changeDate,
                               String changeMessage, String mdChanged) throws Exception {

        for (User user : users) {
            sendEmail(user.getEmail(), subject, status, changeDate, changeMessage, mdChanged);
        }
    }

    /**
     * Send the email message about change of status on a group of metadata records.
     *
     * @param sendTo The recipient email address
     * @param subject Subject to be used for email notices
     * @param status The status being set on the records
     * @param changeDate Datestamp of status change
     * @param changeMessage The message indicating why the status has changed
     */
    protected void sendEmail(String sendTo, String subject, String status, String changeDate, String changeMessage, String mdChanged) throws Exception {
        String message = String.format(LangUtils.translate(context, "statusSendEmail").get(this.language), changeMessage, mdChanged, siteUrl, status,
                changeDate);
       

        if (!emailNotes) {
            context.info("Would send email \nTo: " + sendTo + "\nSubject: " + subject + "\n Message:\n" + message);
        } else {
            MailSender sender = new MailSender(context);
            sender.sendWithReplyTo(host, Integer.parseInt(port), username, password, useSSL, from, fromDescr,
                sendTo, null, replyTo, replyToDescr, subject, message);
        }
    }
}
TOP

Related Classes of org.fao.geonet.kernel.metadata.DefaultStatusActions

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.