<commit_before>/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.curriki.plugin.activitystream.impl;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.xpn.xwiki.util.AbstractXWikiRunnable;
import com.xpn.xwiki.web.Utils;
import org.apache.velocity.VelocityContext;

import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.api.Document;
import com.xpn.xwiki.api.XWiki;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.notify.XWikiDocChangeNotificationInterface;
import com.xpn.xwiki.notify.XWikiNotificationRule;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.plugin.activitystream.api.ActivityEvent;
import com.xpn.xwiki.plugin.activitystream.api.ActivityEventPriority;
import com.xpn.xwiki.plugin.activitystream.api.ActivityEventType;
import com.xpn.xwiki.plugin.activitystream.api.ActivityStreamException;
import com.xpn.xwiki.plugin.activitystream.impl.ActivityEventImpl;
import com.xpn.xwiki.plugin.activitystream.impl.ActivityStreamImpl;
import com.xpn.xwiki.plugin.mailsender.Mail;
import com.xpn.xwiki.plugin.mailsender.MailSenderPlugin;
import com.xpn.xwiki.plugin.spacemanager.api.Space;
import com.xpn.xwiki.plugin.spacemanager.api.SpaceManager;
import com.xpn.xwiki.plugin.spacemanager.api.SpaceManagers;
import com.xpn.xwiki.plugin.spacemanager.api.SpaceUserProfile;
import com.xpn.xwiki.render.XWikiVelocityRenderer;
import org.curriki.plugin.activitystream.plugin.CurrikiActivityStreamPluginApi;
import org.xwiki.context.Execution;
import org.xwiki.observation.event.Event;
import org.xwiki.observation.remote.RemoteObservationManagerContext;

import javax.servlet.http.HttpServletRequest;

public class CurrikiActivityStream extends ActivityStreamImpl implements XWikiDocChangeNotificationInterface
{
    private static final String CURRIKI_SPACE_TYPE = "currikispace";

    private static final String SPACE_CLASS_NAME = "XWiki.SpaceClass";

    public static final String DOCUMENTATION_FILE = "documentation-file";

    public static final String DOCUMENTATION_WIKI = "documentation-wiki";

    public static final String DISCUSSION_TOPIC = "discussion-topic";

    public static final String DISCUSSION_ANSWER = "discussion-answer";

    public CurrikiActivityStream()
    {
        super();
    }

    public void onEvent(Event event, Object source, Object data) {
        System.out.println("onEvent for CurrikiActivityStream! We should not be there.");
        // ignoring these calls, we get the notify calls in principle
    }


    /**
     * {@inheritDoc}
     */
    public void notify(XWikiNotificationRule rule, XWikiDocument newdoc, XWikiDocument olddoc,
        int event, XWikiContext context)
    {
        System.out.println("STREAM: in notify");
        System.out.println("TempAttributes; " + tempStorage.get());

        if(Utils.getComponent(RemoteObservationManagerContext.class).isRemoteState()) {
            System.out.println("Ignoring remote DocumentUpdatedEvent for " + newdoc);
            return;
        }
        try {
            String spaceName = newdoc.getSpace();
            System.out.println("STREAM: in space" + spaceName + " with event " + event);

            if (spaceName == null) {
                return;
            }
            if (spaceName.startsWith("Messages_Group_")) {
                handleMessageEvent(newdoc, olddoc, event, context);
            } else if (spaceName.startsWith("Documentation_Group_")) {
                handleDocumentationEvent(newdoc, olddoc, event, context);
            } else if (spaceName.startsWith("Discussions_Group_")) {
                handleDiscussionsEvent(newdoc, olddoc, event, context);
            } else if (spaceName.startsWith("Coll_Group_")) {
                handleResourceEvent(newdoc, olddoc, event, context);
            } else if (spaceName.startsWith("UserProfiles_Group_")) {
                handleMemberEvent(newdoc, olddoc, event, context);
            }
            // TODO handle events from MemberGroup, AdminGroup and Role_<roleName>Group
        } catch (Throwable t) {
            // Error in activity stream notify should be ignored but logged in the log file
            t.printStackTrace();
        } finally {
            this.clearTempAttributes();
        }
    }


    @Override
    public void addActivityEvent(ActivityEvent event, XWikiDocument doc, XWikiContext context) throws ActivityStreamException {
        super.addActivityEvent(event, doc, context);
        dispatchEventNotification(event, context);
    }

    protected void dispatchEventNotification(final ActivityEvent event, XWikiContext xcontext) {
        AbstractXWikiRunnable runnable = new AbstractXWikiRunnable(XWikiContext.EXECUTIONCONTEXT_KEY, xcontext.clone()) {
            public void runInternal() {
                try {
                    // here we could synchronize on anything we think is useful since we are on separate threads for each event
                    // I wonder what... some representative of the group so we don't get flooded by actions that trigger huge things?
                    XWikiContext xcontext = (XWikiContext) Utils.getComponent(Execution.class).getContext()
                            .getProperty(XWikiContext.EXECUTIONCONTEXT_KEY);
                    Object notificationMailSender = xcontext.getWiki().parseGroovyFromPage("Groups.NotificationMailSender", xcontext);
                    Method sendNotificationEmailForEventMethod = notificationMailSender.getClass().getMethod("sendNotificationEmailForEvent", String.class, ActivityEvent.class);
                    Method initMethod = notificationMailSender.getClass().getMethod("init", com.xpn.xwiki.api.Context.class);
                    initMethod.invoke(notificationMailSender, new com.xpn.xwiki.api.Context(xcontext));
                    sendNotificationEmailForEventMethod.invoke(notificationMailSender, getStreamName(event.getSpace(), xcontext), event);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        new Thread(runnable,"CurrikiActivityStreamDispatchNotification").start();
    }

    protected void handleMessageEvent(XWikiDocument newdoc, XWikiDocument olddoc, int event,
        XWikiContext context)
    {
        System.out.println("handleMessageEvent");
        String streamName = getStreamName(newdoc.getSpace(), context);
        if (streamName == null) {
            return;
        }

        BaseObject article = newdoc.getObject("XWiki.ArticleClass");
        if (article == null) {
            if (olddoc == null) {
                return;
            }
            article = olddoc.getObject("XWiki.ArticleClass");
            if (article == null) {
                return;
            }
            event = XWikiDocChangeNotificationInterface.EVENT_DELETE;
        } else {
            double version = Double.parseDouble(newdoc.getVersion());<commit_msg>attempt at solving CURRIKI-6587 Group Leader Notifications: Discussion Comment missing body text. paul<commit_after>/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.curriki.plugin.activitystream.impl;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.xpn.xwiki.util.AbstractXWikiRunnable;
import com.xpn.xwiki.web.Utils;
import org.apache.velocity.VelocityContext;

import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.api.Document;
import com.xpn.xwiki.api.XWiki;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.notify.XWikiDocChangeNotificationInterface;
import com.xpn.xwiki.notify.XWikiNotificationRule;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.plugin.activitystream.api.ActivityEvent;
import com.xpn.xwiki.plugin.activitystream.api.ActivityEventPriority;
import com.xpn.xwiki.plugin.activitystream.api.ActivityEventType;
import com.xpn.xwiki.plugin.activitystream.api.ActivityStreamException;
import com.xpn.xwiki.plugin.activitystream.impl.ActivityEventImpl;
import com.xpn.xwiki.plugin.activitystream.impl.ActivityStreamImpl;
import com.xpn.xwiki.plugin.mailsender.Mail;
import com.xpn.xwiki.plugin.mailsender.MailSenderPlugin;
import com.xpn.xwiki.plugin.spacemanager.api.Space;
import com.xpn.xwiki.plugin.spacemanager.api.SpaceManager;
import com.xpn.xwiki.plugin.spacemanager.api.SpaceManagers;
import com.xpn.xwiki.plugin.spacemanager.api.SpaceUserProfile;
import com.xpn.xwiki.render.XWikiVelocityRenderer;
import org.curriki.plugin.activitystream.plugin.CurrikiActivityStreamPluginApi;
import org.xwiki.context.Execution;
import org.xwiki.observation.event.Event;
import org.xwiki.observation.remote.RemoteObservationManagerContext;

import javax.servlet.http.HttpServletRequest;

public class CurrikiActivityStream extends ActivityStreamImpl implements XWikiDocChangeNotificationInterface
{
    private static final String CURRIKI_SPACE_TYPE = "currikispace";

    private static final String SPACE_CLASS_NAME = "XWiki.SpaceClass";

    public static final String DOCUMENTATION_FILE = "documentation-file";

    public static final String DOCUMENTATION_WIKI = "documentation-wiki";

    public static final String DISCUSSION_TOPIC = "discussion-topic";

    public static final String DISCUSSION_ANSWER = "discussion-answer";

    public CurrikiActivityStream()
    {
        super();
    }

    public void onEvent(Event event, Object source, Object data) {
        System.out.println("onEvent for CurrikiActivityStream! We should not be there.");
        // ignoring these calls, we get the notify calls in principle
    }


    /**
     * {@inheritDoc}
     */
    public void notify(XWikiNotificationRule rule, XWikiDocument newdoc, XWikiDocument olddoc,
        int event, XWikiContext context)
    {
        System.out.println("STREAM: in notify");
        System.out.println("TempAttributes; " + tempStorage.get());

        if(Utils.getComponent(RemoteObservationManagerContext.class).isRemoteState()) {
            System.out.println("Ignoring remote DocumentUpdatedEvent for " + newdoc);
            return;
        }
        try {
            String spaceName = newdoc.getSpace();
            System.out.println("STREAM: in space" + spaceName + " with event " + event);

            if (spaceName == null) {
                return;
            }
            if (spaceName.startsWith("Messages_Group_")) {
                handleMessageEvent(newdoc, olddoc, event, context);
            } else if (spaceName.startsWith("Documentation_Group_")) {
                handleDocumentationEvent(newdoc, olddoc, event, context);
            } else if (spaceName.startsWith("Discussions_Group_")) {
                handleDiscussionsEvent(newdoc, olddoc, event, context);
            } else if (spaceName.startsWith("Coll_Group_")) {
                handleResourceEvent(newdoc, olddoc, event, context);
            } else if (spaceName.startsWith("UserProfiles_Group_")) {
                handleMemberEvent(newdoc, olddoc, event, context);
            }
            // TODO handle events from MemberGroup, AdminGroup and Role_<roleName>Group
        } catch (Throwable t) {
            // Error in activity stream notify should be ignored but logged in the log file
            t.printStackTrace();
        } finally {
            this.clearTempAttributes();
        }
    }


    @Override
    public void addActivityEvent(ActivityEvent event, XWikiDocument doc, XWikiContext context) throws ActivityStreamException {
        super.addActivityEvent(event, doc, context);
        dispatchEventNotification(event, context);
    }

    protected void dispatchEventNotification(final ActivityEvent event, XWikiContext xcontext) {
        final Map<String, Object> temp =  tempStorage.get();
        AbstractXWikiRunnable runnable = new AbstractXWikiRunnable(XWikiContext.EXECUTIONCONTEXT_KEY, xcontext.clone()) {
            public void runInternal() {
                try {
                    // here we could synchronize on anything we think is useful since we are on separate threads for each event
                    // I wonder what... some representative of the group so we don't get flooded by actions that trigger huge things?
                    XWikiContext xcontext = (XWikiContext) Utils.getComponent(Execution.class).getContext()
                            .getProperty(XWikiContext.EXECUTIONCONTEXT_KEY);
                    tempStorage.set(temp);
                    Object notificationMailSender = xcontext.getWiki().parseGroovyFromPage("Groups.NotificationMailSender", xcontext);
                    Method sendNotificationEmailForEventMethod = notificationMailSender.getClass().getMethod("sendNotificationEmailForEvent", String.class, ActivityEvent.class);
                    Method initMethod = notificationMailSender.getClass().getMethod("init", com.xpn.xwiki.api.XWiki.class);
                    xcontext.setWiki(xcontext.getWiki());
                    initMethod.invoke(notificationMailSender, new com.xpn.xwiki.api.XWiki(xcontext.getWiki(), xcontext));
                    sendNotificationEmailForEventMethod.invoke(notificationMailSender, getStreamName(event.getSpace(), xcontext), event);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        new Thread(runnable,"CurrikiActivityStreamDispatchNotification").start();
    }

    protected void handleMessageEvent(XWikiDocument newdoc, XWikiDocument olddoc, int event,
        XWikiContext context)
    {
        System.out.println("handleMessageEvent");
        String streamName = getStreamName(newdoc.getSpace(), context);
        if (streamName == null) {
            return;
        }

        BaseObject article = newdoc.getObject("XWiki.ArticleClass");
        if (article == null) {
            if (olddoc == null) {
                return;
            }
            article = olddoc.getObject("XWiki.ArticleClass");
            if (article == null) {
                return;
            }
            event = XWikiDocChangeNotificationInterface.EVENT_DELETE;
        } else {
            double version = Double.parseDouble(newdoc.getVersion());
{'fraction_non_alphanumeric': 0.08840534659620765, 'fraction_numerical': 0.0018650917003419335, 'mean_word_length': 3.120389344262295, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4829583', 'n_tokens_mistral': 4381, 'n_tokens_neox': 4258, 'n_words': 1067}