com.xpn.xwiki.plugin.invitationmanager.impl.InvitationManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.xpn.xwiki.plugin.invitationmanager.impl.InvitationManagerImpl.java

Source

/*
 * 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 com.xpn.xwiki.plugin.invitationmanager.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.RandomStringUtils;
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.objects.classes.BaseClass;
import com.xpn.xwiki.plugin.invitationmanager.api.Invitation;
import com.xpn.xwiki.plugin.invitationmanager.api.InvitationManager;
import com.xpn.xwiki.plugin.invitationmanager.api.InvitationManagerException;
import com.xpn.xwiki.plugin.invitationmanager.api.JoinRequest;
import com.xpn.xwiki.plugin.invitationmanager.api.JoinRequestStatus;
import com.xpn.xwiki.plugin.invitationmanager.api.MembershipRequest;
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.plugin.spacemanager.impl.SpaceUserProfileImpl;
import com.xpn.xwiki.render.XWikiVelocityRenderer;

/**
 * The default implementation for {@link InvitationManager}
 * 
 * @version $Id$
 */
@SuppressWarnings("unchecked")
public class InvitationManagerImpl implements InvitationManager {
    public static interface JoinRequestAction {
        String CREATE = "Create";

        String SEND = "Send";

        String ACCEPT = "Accept";

        String REJECT = "Reject";
    }

    public static final String USER_PROFILES_DEFAULT = "1";

    public static final String SPACE_VELOCITY_KEY = "space";

    public static final String INVITATION_VELOCITY_KEY = "invitation";

    public static final String MEMBERSHIP_REQUEST_VELOCITY_KEY = "membershiprequest";

    public static final String INVITATION_CLASS_NAME = "XWiki.InvitationClass";

    public static final String MEMBERSHIP_REQUEST_CLASS_NAME = "XWiki.MembershipRequestClass";

    private boolean mailNotification = true;

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#acceptInvitation(String, String, String, XWikiContext)
     */
    public boolean acceptInvitation(String space, String email, String code, XWikiContext context)
            throws InvitationManagerException {
        try {
            Invitation invitation = getInvitation(space, email, context);
            if (code.equals(invitation.getCode()) && invitation.getStatus() == JoinRequestStatus.SENT) {
                if (!invitation.isOpen()) {
                    invitation.setStatus(JoinRequestStatus.ACCEPTED);
                    invitation.setResponseDate(new Date());
                    invitation.setInvitee(context.getUser());
                    invitation.saveWithProgrammingRights();
                }

                if (isWithUserProfiles(context)) {
                    // create and save a new space user profile based on the HTTP request
                    createSpaceUserProfile(space, context);
                }

                // update the list of space members and their roles
                addMember(space, context.getUser(), invitation.getRoles(), context);

                // create a custom invitation for the currently logged-in user
                customizeInvitation(invitation, JoinRequestStatus.ACCEPTED, context);
                return true;
            } else {
                return false;
            }
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#acceptInvitation(String, String, String, XWikiContext)
     */
    public boolean verifyInvitation(String space, String email, String code, XWikiContext context)
            throws InvitationManagerException {
        try {
            Invitation invitation = getInvitation(space, email, context);
            if (code.equals(invitation.getCode()) && invitation.getStatus() == JoinRequestStatus.SENT) {
                return true;
            } else {
                return false;
            }
        } catch (XWikiException e) {
            return false;
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#acceptInvitation(String, XWikiContext)
     */
    public boolean acceptInvitation(String space, XWikiContext context) throws InvitationManagerException {
        try {
            Invitation invitation = getInvitation(space, context.getUser(), context);

            // if the invitation does not exist we need to return false
            if (invitation.isNew())
                return false;

            int status = invitation.getStatus();
            if (status == JoinRequestStatus.SENT || status == JoinRequestStatus.REFUSED) {
                // update the invitation object
                invitation.setResponseDate(new Date());
                invitation.setStatus(JoinRequestStatus.ACCEPTED);

                if (isWithUserProfiles(context)) {
                    // create and save a new space user profile based on the HTTP request
                    createSpaceUserProfile(space, context);
                }

                // update the list of members and their roles
                addMember(space, context.getUser(), invitation.getRoles(), context);
                // save the invitation status
                invitation.saveWithProgrammingRights();
                return true;
            } else {
                return false;
            }
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#acceptInvitation(String, String, String, XWikiContext)
     */
    public boolean verifyInvitation(String space, XWikiContext context) throws InvitationManagerException {
        try {
            Invitation invitation = getInvitation(space, context.getUser(), context);
            if ((invitation != null) && (invitation.getStatus() == JoinRequestStatus.SENT))
                return true;
            else
                return false;
        } catch (XWikiException e) {
            return false;
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#acceptMembership(String, String, String, XWikiContext)
     */
    public boolean acceptMembership(String space, String userName, String templateMail, XWikiContext context)
            throws InvitationManagerException {
        try {
            MembershipRequest request = getMembershipRequest(space, userName, context);

            // if the invitation does not exist we need to return false
            if (request.isNew())
                return false;

            int status = request.getStatus();
            if (status == JoinRequestStatus.SENT || status == JoinRequestStatus.REFUSED) {
                // update the membership request object
                request.setResponseDate(new Date());
                request.setResponder(context.getUser());
                request.setStatus(JoinRequestStatus.ACCEPTED);
                // send notification mail
                sendMail(JoinRequestAction.ACCEPT, request, templateMail, context);

                // create and save a new space user profile based on the membership request
                createSpaceUserProfile(space, request, context);

                // update the list of members and their roles
                addMember(space, userName, request.getRoles(), context);

                // save after adding user and sending email
                request.saveWithProgrammingRights();
                return true;
            } else {
                return false;
            }
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#acceptMembership(String, String, XWikiContext)
     */
    public boolean acceptMembership(String space, String userName, XWikiContext context)
            throws InvitationManagerException {
        String templateMail = getDefaultTemplateMailDocumentName(space, "Request", JoinRequestAction.ACCEPT,
                context);
        return acceptMembership(space, userName, templateMail, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#cancelInvitation(String, String, XWikiContext)
     */
    public void cancelInvitation(String userNameOrMail, String space, XWikiContext context)
            throws InvitationManagerException {
        try {
            Invitation invitation = getInvitation(space, userNameOrMail, context);
            if (invitation.getStatus() == JoinRequestStatus.SENT) {
                invitation.setStatus(JoinRequestStatus.CANCELLED);
                invitation.saveWithProgrammingRights();
            }
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#cancelMembershipRequest(String, XWikiContext)
     */
    public void cancelMembershipRequest(String space, XWikiContext context) throws InvitationManagerException {
        try {
            MembershipRequest request = getMembershipRequest(space, context.getUser(), context);
            if (request.getStatus() == JoinRequestStatus.SENT) {
                request.setStatus(JoinRequestStatus.CANCELLED);
                request.saveWithProgrammingRights();
            }
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(int, int, int, XWikiContext)
     */
    public List getInvitations(int status, int start, int count, XWikiContext context) {
        try {
            Invitation prototype = createInvitation(context.getUser(), null, context);
            prototype.setStatus(status);
            return getInvitations(prototype, start, count, context);
        } catch (XWikiException e) {
            return Collections.EMPTY_LIST;
        }
    }

    public void initClasses(XWikiContext context) throws XWikiException {
        getInvitationClass(context);
        getMembershipRequestClass(context);
    }

    /**
     * @param context Xwiki context
     * @return Returns the Invitation Class as defined by the extension
     * @throws XWikiException
     */
    protected BaseClass getInvitationClass(XWikiContext context) throws XWikiException {
        String className = getInvitationClassName();
        String classContent = "1 XWiki Invitation Class";

        return getJoinRequestClass(className, classContent, context);
    }

    /**
     * @param context Xwiki context
     * @return Returns the Membership Class as defined by the extension
     * @throws XWikiException
     */
    protected BaseClass getMembershipRequestClass(XWikiContext context) throws XWikiException {
        String className = getMembershipRequestClassName();
        String classContent = "1 XWiki Membership Request Class";

        return getJoinRequestClass(className, classContent, context);
    }

    private BaseClass getJoinRequestClass(String className, String classContent, XWikiContext context)
            throws XWikiException {
        XWikiDocument doc;
        com.xpn.xwiki.XWiki xwiki = context.getWiki();
        boolean needsUpdate = false;

        try {
            doc = xwiki.getDocument(className, context);
        } catch (Exception e) {
            doc = new XWikiDocument();
            doc.setFullName(className);
            needsUpdate = true;
        }

        BaseClass bclass = doc.getxWikiClass();
        bclass.setName(className);

        needsUpdate |= bclass.addDateField(JoinRequestImpl.JoinRequestFields.REQUEST_DATE, "Request Date");
        needsUpdate |= bclass.addDateField(JoinRequestImpl.JoinRequestFields.RESPONSE_DATE, "Response Date");
        needsUpdate |= bclass.addTextAreaField(JoinRequestImpl.JoinRequestFields.TEXT, "Text", 80, 10);
        needsUpdate |= bclass.addTextAreaField(JoinRequestImpl.JoinRequestFields.MAP, "Map", 80, 10);
        needsUpdate |= bclass.addTextField(JoinRequestImpl.JoinRequestFields.SPACE, "Space", 32);
        needsUpdate |= bclass.addStaticListField(JoinRequestImpl.JoinRequestFields.STATUS, "Status", 1, false,
                "0=none|1=created|2=sent|3=accepted|4=refused|5=cancelled", "select");
        needsUpdate |= bclass.addDBListField(JoinRequestImpl.JoinRequestFields.ROLES, "Roles", 5, true, "");

        if (className.equals(getInvitationClassName())) {
            needsUpdate |= bclass.addTextField(InvitationImpl.InvitationFields.CODE, "Code", 40);
            needsUpdate |= bclass.addTextField(InvitationImpl.InvitationFields.INVITEE, "Invitee", 40);
            needsUpdate |= bclass.addTextField(InvitationImpl.InvitationFields.INVITEE, "Inviter", 40);
            needsUpdate |= bclass.addBooleanField(InvitationImpl.InvitationFields.OPEN, "Open", "yesno");
        } else if (className.equals(getMembershipRequestClassName())) {
            needsUpdate |= bclass.addTextField(MembershipRequestImpl.MembershipRequestFields.REQUESTER, "Requester",
                    40);
            needsUpdate |= bclass.addTextField(MembershipRequestImpl.MembershipRequestFields.RESPONDER, "Responder",
                    40);
        }

        String content = doc.getContent();
        if ((content == null) || (content.equals(""))) {
            needsUpdate = true;
            doc.setContent(classContent);
            doc.setSyntaxId(XWikiDocument.XWIKI10_SYNTAXID);
        }

        if (needsUpdate)
            xwiki.saveDocument(doc, context);
        return bclass;
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(int, int, XWikiContext)
     */
    public List getInvitations(int start, int count, XWikiContext context) {
        return getInvitations(JoinRequestStatus.ANY, start, count, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(int, XWikiContext)
     */
    public List getInvitations(int status, XWikiContext context) {
        return getInvitations(status, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(Invitation, int, int, XWikiContext)
     */
    public List getInvitations(Invitation prototype, int start, int count, XWikiContext context) {
        try {
            String className = getInvitationClassName();
            StringBuffer fromClause = new StringBuffer("from XWikiDocument as doc, BaseObject as obj");
            StringBuffer whereClause = new StringBuffer(
                    "where doc.fullName=obj.name and obj.className = '" + className + "'");

            String space = prototype.getSpace();
            String invitee = prototype.getInvitee();
            if (!"".equals(space) && !"".equals(invitee)) {
                Invitation invitation = getInvitation(space, invitee, context);
                // find a better way of testing if the invitation is new
                if (((Document) invitation).isNew()) {
                    return Collections.EMPTY_LIST;
                }
                List list = new ArrayList();
                list.add(invitation);
                return list;
            } else if (!"".equals(space)) {
                fromClause.append(", StringProperty as space");
                whereClause.append(" and obj.id=space.id.id and space.id.name='"
                        + InvitationImpl.InvitationFields.SPACE + "' and space.value='" + space + "'");
            } else if (!"".equals(invitee)) {
                fromClause.append(" StringProperty as invitee");
                whereClause.append(" and obj.id=invitee.id.id and invitee.id.name='"
                        + InvitationImpl.InvitationFields.INVITEE + "' and invitee.value='" + invitee + "'");
            }

            int status = prototype.getStatus();
            if (status != JoinRequestStatus.ANY) {
                fromClause.append(", StringProperty as status");
                whereClause.append(" and obj.id=status.id.id and status.id.name='"
                        + InvitationImpl.InvitationFields.STATUS + "' and status.value='" + status + "'");
            }

            List roles = prototype.getRoles();
            if (roles != null && roles.size() > 0) {
                String role = (String) prototype.getRoles().get(0);
                fromClause.append(", DBStringListProperty as roles join roles.list as role");
                whereClause.append(" and obj.id=roles.id.id and roles.id.name='"
                        + InvitationImpl.InvitationFields.ROLES + "' and instr(role.id, '" + role + "')>0");
            }

            String inviter = prototype.getInviter();
            if (!"".equals(inviter)) {
                fromClause.append(" StringProperty as inviter");
                whereClause.append(" and obj.id=inviter.id.id and inviter.id.name='"
                        + InvitationImpl.InvitationFields.INVITER + "' and inviter.value='" + inviter + "'");
            }

            String sql = "select distinct doc.fullName " + fromClause.toString() + " " + whereClause.toString();

            return wrapInvitations(context.getWiki().getStore().search(sql, count, start, context), context);
        } catch (XWikiException e) {
            e.printStackTrace();
            return Collections.EMPTY_LIST;
        }
    }

    private List wrapInvitations(List list, XWikiContext context) {
        ArrayList result = new ArrayList();
        if (list == null)
            return null;
        for (int i = 0; i < list.size(); i++) {
            String inviteDocName = (String) list.get(i);
            try {
                result.add(new InvitationImpl(inviteDocName, this, context));
            } catch (XWikiException e) {
                // let's not a single invitation break our requests
                e.printStackTrace();
            }
        }
        return result;
    }

    private List wrapMembershipRequests(List list, XWikiContext context) {
        ArrayList result = new ArrayList();
        if (list == null)
            return null;
        for (int i = 0; i < list.size(); i++) {
            String inviteDocName = (String) list.get(i);
            try {
                result.add(new MembershipRequestImpl(inviteDocName, this, context));
            } catch (XWikiException e) {
                // let's not a single invitation break our requests
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(Invitation, XWikiContext)
     */
    public List getInvitations(Invitation prototype, XWikiContext context) {
        return getInvitations(prototype, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(String, int, int, int, XWikiContext)
     */
    public List getInvitations(String space, int status, int start, int count, XWikiContext context) {
        return getInvitations(space, status, null, start, count, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(String, int, int, XWikiContext)
     */
    public List getInvitations(String space, int start, int count, XWikiContext context) {
        return getInvitations(space, JoinRequestStatus.ANY, start, count, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(String, int, String, int, int, XWikiContext)
     */
    public List getInvitations(String space, int status, String role, int start, int count, XWikiContext context) {
        try {
            Invitation prototype = createInvitation(null, space, context);
            if ((role != null) && !"".equals(role)) {
                List roles = new ArrayList();
                roles.add(role);
                prototype.setRoles(roles);
            }
            prototype.setStatus(status);
            return getInvitations(prototype, start, count, context);
        } catch (XWikiException e) {
            e.printStackTrace();
            return Collections.EMPTY_LIST;
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(String, int, String, XWikiContext)
     */
    public List getInvitations(String space, int status, String role, XWikiContext context) {
        return getInvitations(space, status, role, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(String, int, XWikiContext)
     */
    public List getInvitations(String space, int status, XWikiContext context) {
        return getInvitations(space, status, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(String, String, int, int, XWikiContext)
     */
    public List getInvitations(String space, String role, int start, int count, XWikiContext context) {
        return getInvitations(space, 0, role, start, count, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(String, String, XWikiContext)
     */
    public List getInvitations(String space, String role, XWikiContext context) {
        return getInvitations(space, role, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(String, XWikiContext)
     */
    public List getInvitations(String space, XWikiContext context) {
        return getInvitations(space, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getInvitations(XWikiContext)
     */
    public List getInvitations(XWikiContext context) {
        return getInvitations(0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(int, int, int, XWikiContext)
     */
    public List getMembershipRequests(int status, int start, int count, XWikiContext context) {
        try {
            MembershipRequest prototype = createMembershipRequest(context.getUser(), null, context);
            prototype.setStatus(status);
            return getMembershipRequests(prototype, start, count, context);
        } catch (XWikiException e) {
            e.printStackTrace();
            return Collections.EMPTY_LIST;
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(int, int, XWikiContext)
     */
    public List getMembershipRequests(int start, int count, XWikiContext context) {
        return getMembershipRequests(JoinRequestStatus.ANY, start, count, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(int, XWikiContext)
     */
    public List getMembershipRequests(int status, XWikiContext context) {
        return getMembershipRequests(status, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(MembershipRequest, int, int, XWikiContext)
     */
    public List getMembershipRequests(MembershipRequest prototype, int start, int count, XWikiContext context) {
        try {
            String className = getMembershipRequestClassName();
            StringBuffer fromClause = new StringBuffer("from XWikiDocument as doc, BaseObject as obj");
            StringBuffer whereClause = new StringBuffer(
                    "where doc.fullName=obj.name and obj.className = '" + className + "'");

            String space = prototype.getSpace();
            String requester = prototype.getRequester();
            if (!"".equals(space) && !"".equals(requester)) {
                MembershipRequest request = getMembershipRequest(space, requester, context);
                // find a better way of testing if the request is new
                if (((Document) request).isNew()) {
                    return Collections.EMPTY_LIST;
                }
                List list = new ArrayList();
                list.add(request);
                return list;
            } else if (!"".equals(space)) {
                fromClause.append(", StringProperty as space");
                whereClause.append(" and obj.id=space.id.id and space.id.name='"
                        + MembershipRequestImpl.MembershipRequestFields.SPACE + "' and space.value='" + space
                        + "'");
            } else if (!"".equals(requester)) {
                fromClause.append(" StringProperty as requester");
                whereClause.append(" and obj.id=requester.id.id and requester.id.name='"
                        + MembershipRequestImpl.MembershipRequestFields.REQUESTER + "' and requester.value='"
                        + requester + "'");
            }

            int status = prototype.getStatus();
            if (status != JoinRequestStatus.ANY) {
                fromClause.append(", StringProperty as status");
                whereClause.append(" and obj.id=status.id.id and status.id.name='"
                        + MembershipRequestImpl.MembershipRequestFields.STATUS + "' and status.value='" + status
                        + "'");
            }

            List roles = prototype.getRoles();
            if (roles != null && roles.size() > 0) {
                String role = (String) prototype.getRoles().get(0);
                fromClause.append(", DBStringListProperty as roles join roles.list as role");
                whereClause.append(" and obj.id=roles.id.id and roles.id.name='"
                        + MembershipRequestImpl.MembershipRequestFields.ROLES + "' and instr(role.id, '" + role
                        + "')>0");
            }

            String responder = prototype.getResponder();
            if (!"".equals(responder)) {
                fromClause.append(" StringProperty as responder");
                whereClause.append(" and obj.id=responder.id.id and responder.id.name='"
                        + MembershipRequestImpl.MembershipRequestFields.RESPONDER + "' and responder.value='"
                        + responder + "'");
            }

            String sql = "select distinct doc.fullName " + fromClause.toString() + " " + whereClause.toString();
            return wrapMembershipRequests(context.getWiki().getStore().search(sql, count, start, context), context);
        } catch (XWikiException e) {
            e.printStackTrace();
            return Collections.EMPTY_LIST;
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(MembershipRequest, XWikiContext)
     */
    public List getMembershipRequests(MembershipRequest prototype, XWikiContext context) {
        return getMembershipRequests(prototype, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(String, int, int, int, XWikiContext)
     */
    public List getMembershipRequests(String space, int status, int start, int count, XWikiContext context) {
        return getMembershipRequests(space, status, null, start, count, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(String, int, int, XWikiContext)
     */
    public List getMembershipRequests(String space, int start, int count, XWikiContext context) {
        return getMembershipRequests(space, JoinRequestStatus.ANY, start, count, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(String, int, String, int, int, XWikiContext)
     */
    public List getMembershipRequests(String space, int status, String role, int start, int count,
            XWikiContext context) {
        try {
            MembershipRequest prototype = createMembershipRequest(null, space, context);
            if ((role != null) && !"".equals(role)) {
                List roles = new ArrayList();
                roles.add(role);
                prototype.setRoles(roles);
            }
            prototype.setStatus(status);
            return getMembershipRequests(prototype, start, count, context);
        } catch (XWikiException e) {
            e.printStackTrace();
            return Collections.EMPTY_LIST;
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(String, int, String, XWikiContext)
     */
    public List getMembershipRequests(String space, int status, String role, XWikiContext context) {
        return getMembershipRequests(space, status, role, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(String, int, XWikiContext)
     */
    public List getMembershipRequests(String space, int status, XWikiContext context) {
        return getMembershipRequests(space, status, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(String, String, int, int, XWikiContext)
     */
    public List getMembershipRequests(String space, String role, int start, int count, XWikiContext context) {
        return getMembershipRequests(space, 0, role, start, count, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(String, String, XWikiContext)
     */
    public List getMembershipRequests(String space, String role, XWikiContext context) {
        return getMembershipRequests(space, role, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(String, XWikiContext)
     */
    public List getMembershipRequests(String space, XWikiContext context) {
        return getMembershipRequests(space, 0, 0, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#getMembershipRequests(XWikiContext)
     */
    public List getMembershipRequests(XWikiContext context) {
        return getMembershipRequests(0, 0, context);
    }

    private void addToAlreadyMember(String user, XWikiContext context) {
        List list = (List) context.get("im_alreadymember");
        if (list == null) {
            list = new ArrayList();
            context.put("im_alreadymember", list);
        }
        list.add(user);
    }

    private void addToAlreadyInvited(String user, XWikiContext context) {
        List list = (List) context.get("im_alreadyinvited");
        if (list == null) {
            list = new ArrayList();
            context.put("im_alreadyinvited", list);
        }
        list.add(user);
    }

    /**
     * {@inheritDoc}
     * 
     * @see com.xpn.xwiki.plugin.invitationmanager.api.InvitationManager#inviteUser(String, String,
     *      boolean, List, String, Map, XWikiContext)
     */
    public void inviteUser(String wikiNameOrMailAddress, String space, boolean open, List roles,
            String templateMail, Map map, XWikiContext context) throws InvitationManagerException {
        try {
            if (wikiNameOrMailAddress == null || wikiNameOrMailAddress.trim().length() == 0) {
                throw new InvitationManagerException(InvitationManagerException.MODULE_PLUGIN_INVITATIONMANAGER,
                        InvitationManagerException.ERROR_INVITATION_INVITEE_MISSING, "Invitee missing");
            }

            wikiNameOrMailAddress = wikiNameOrMailAddress.trim();
            String registeredUser = getRegisteredUser(wikiNameOrMailAddress, context);
            String invitee;
            if (registeredUser == null) {
                // it should be an e-mail address
                if (!isEmailAddress(wikiNameOrMailAddress)) {
                    throw new InvitationManagerException(InvitationManagerException.MODULE_PLUGIN_INVITATIONMANAGER,
                            InvitationManagerException.ERROR_INVITATION_INVITEE_EMAIL_INVALID,
                            "Invalid invitee e-mail address");
                }
                // hide the e-mail address (only for invitation document name)
                invitee = encodeEmailAddress(wikiNameOrMailAddress);
            } else {
                invitee = registeredUser;
                if (isMember(space, invitee, context)) {
                    addToAlreadyMember(invitee, context);
                    throw new InvitationManagerException(InvitationManagerException.MODULE_PLUGIN_INVITATIONMANAGER,
                            InvitationManagerException.ERROR_INVITATION_ALREADY_MEMBER, "Already member");
                }
            }

            // create the invitation object
            Invitation invitation = createInvitation(invitee, space, context);

            // if we get here it means the invitee is not a member of the space
            if (!invitation.isNew()) {
                int status = invitation.getStatus();
                // maybe it's an old invitation
                if (JoinRequestStatus.CREATED == status || JoinRequestStatus.SENT == status) {
                    // is's a new one
                    addToAlreadyInvited(invitee, context);
                    throw new InvitationManagerException(InvitationManagerException.MODULE_PLUGIN_INVITATIONMANAGER,
                            InvitationManagerException.ERROR_INVITATION_ALREADY_EXISTS, "Already invited");
                } else {
                    // is's an old one
                    // in this case we overwrite the invitation
                }
            }

            invitation.setInviter(context.getUser());
            invitation.setMap(map);
            invitation.setOpen(open);
            invitation.setRequestDate(new Date());
            invitation.setRoles(roles);
            invitation.setStatus(JoinRequestStatus.SENT);
            if (registeredUser == null) {
                invitation.setCode(generateInvitationCode());
                // make the e-mail address available in the invitee field
                invitation.setInvitee(wikiNameOrMailAddress);
            } else {
                invitation.setInvitee(registeredUser);
            }

            // send a notification mail
            if (templateMail == null) {
                templateMail = getDefaultTemplateMailDocumentName(space, "Invitation", JoinRequestAction.SEND,
                        context);
            }
            sendMail(JoinRequestAction.SEND, invitation, templateMail, context);

            // save invitation after
            invitation.saveWithProgrammingRights();
        } catch (InvitationManagerException e) {
            throw e;
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see com.xpn.xwiki.plugin.invitationmanager.api.InvitationManager#inviteUser(String, String,
     *      boolean, List, String, XWikiContext)
     */
    public void inviteUser(String user, String space, boolean open, List roles, String templateMail,
            XWikiContext context) throws InvitationManagerException {
        inviteUser(user, space, open, roles, templateMail, Collections.EMPTY_MAP, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see com.xpn.xwiki.plugin.invitationmanager.api.InvitationManager#inviteUser(String, String,
     *      boolean, List, XWikiContext)
     */
    public void inviteUser(String user, String space, boolean open, List roles, XWikiContext context)
            throws InvitationManagerException {
        String templateMail = getDefaultTemplateMailDocumentName(space, "Invitation", JoinRequestAction.SEND,
                context);
        inviteUser(user, space, open, roles, templateMail, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see com.xpn.xwiki.plugin.invitationmanager.api.InvitationManager#inviteUser(String, String,
     *      boolean, String, XWikiContext)
     */
    public void inviteUser(String user, String space, boolean open, String role, XWikiContext context)
            throws InvitationManagerException {
        List roles = new ArrayList();
        roles.add(role);
        inviteUser(user, space, open, roles, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see com.xpn.xwiki.plugin.invitationmanager.api.InvitationManager#inviteUser(String, String,
     *      boolean, XWikiContext)
     */
    public void inviteUser(String user, String space, boolean open, XWikiContext context)
            throws InvitationManagerException {
        inviteUser(user, space, open, Collections.EMPTY_LIST, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#rejectInvitation(String, String, String, XWikiContext)
     */
    public void rejectInvitation(String space, String email, String code, XWikiContext context)
            throws InvitationManagerException {
        try {
            Invitation invitation = getInvitation(space, email, context);
            if (code.equals(invitation.getCode()) && invitation.getStatus() == JoinRequestStatus.SENT) {
                if (!invitation.isOpen()) {
                    invitation.setStatus(JoinRequestStatus.REFUSED);
                    invitation.setResponseDate(new Date());
                    invitation.setInvitee(context.getUser());
                    invitation.saveWithProgrammingRights();
                }
                // create a custom invitation for the currently logged-in user
                customizeInvitation(invitation, JoinRequestStatus.REFUSED, context);
            }
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#rejectInvitation(String, XWikiContext)
     */
    public void rejectInvitation(String space, XWikiContext context) throws InvitationManagerException {
        try {
            Invitation invitation = getInvitation(space, context.getUser(), context);
            if (invitation.getStatus() == JoinRequestStatus.SENT) {
                invitation.setStatus(JoinRequestStatus.REFUSED);
                invitation.setResponseDate(new Date());
                invitation.saveWithProgrammingRights();
            }
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#rejectMembership(String, String, String, XWikiContext)
     */
    public void rejectMembership(String space, String userName, String templateMail, XWikiContext context)
            throws InvitationManagerException {
        try {
            MembershipRequest request = getMembershipRequest(space, userName, context);
            if (request.getStatus() == JoinRequestStatus.SENT) {
                request.setStatus(JoinRequestStatus.REFUSED);
                request.setResponseDate(new Date());
                request.setResponder(context.getUser());
                sendMail(JoinRequestAction.REJECT, request, templateMail, context);
                request.saveWithProgrammingRights();
            }
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#rejectMembership(String, String, XWikiContext)
     */
    public void rejectMembership(String space, String userName, XWikiContext context)
            throws InvitationManagerException {
        String templateMail = getDefaultTemplateMailDocumentName(space, "Request", JoinRequestAction.REJECT,
                context);
        rejectMembership(space, userName, templateMail, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#requestMembership(String, String, List, Map, XWikiContext)
     */
    public void requestMembership(String space, String message, List roles, Map map, XWikiContext context)
            throws InvitationManagerException {
        try {
            MembershipRequest request = createMembershipRequest(context.getUser(), space, context);
            request.setMap(map);
            request.setRequestDate(new Date());
            request.setRoles(roles);
            request.setStatus(JoinRequestStatus.SENT);
            request.setText(message);
            // e-mail notification is sent to user's e-mail address informing them of their "Pending
            // approval" status
            String requestSentMailTemplate = getDefaultTemplateMailDocumentName(space, "Request",
                    JoinRequestAction.CREATE, context);
            sendMail(JoinRequestAction.CREATE, request, requestSentMailTemplate, context);
            // send "Membership Request awaiting approval" notification via e-mail to the space
            // administrator(s)
            String requestPendingMailTemplate = getDefaultTemplateMailDocumentName(space, "Request",
                    JoinRequestAction.SEND, context);
            sendMail(JoinRequestAction.SEND, request, requestPendingMailTemplate, context);
            request.saveWithProgrammingRights();
        } catch (XWikiException e) {
            throw new InvitationManagerException(e);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#requestMembership(String, String, List, XWikiContext)
     */
    public void requestMembership(String space, String message, List roles, XWikiContext context)
            throws InvitationManagerException {
        requestMembership(space, message, roles, Collections.EMPTY_MAP, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#requestMembership(String, String, String, XWikiContext)
     */
    public void requestMembership(String space, String message, String role, XWikiContext context)
            throws InvitationManagerException {
        List roles = new ArrayList();
        roles.add(role);
        requestMembership(space, message, roles, context);
    }

    /**
     * {@inheritDoc}
     * 
     * @see InvitationManager#requestMembership(String, String, XWikiContext)
     */
    public void requestMembership(String space, String message, XWikiContext context)
            throws InvitationManagerException {
        requestMembership(space, message, Collections.EMPTY_LIST, context);
    }

    /**
     * @return the name of the document (wiki page) that is the default mail template to be used for
     *         notifying the execution of the specified action on a request of class
     *         <code>joinRequestClass</code> related to the given space.
     */
    private String getDefaultTemplateMailDocumentName(String space, String type, String action,
            XWikiContext context) {
        String docName = space + "." + "MailTemplate" + action + type;
        try {
            if (context.getWiki().getDocument(docName, context).isNew()) {
                docName = null;
            }
        } catch (XWikiException e) {
            docName = null;
        }
        if (docName == null) {
            docName = getDefaultResourceSpace(context) + "." + "MailTemplate" + action + type;
        }

        return docName;
    }

    private String getDefaultResourceSpace(XWikiContext context) {
        return context.getWiki().Param("xwiki.invitationmanager.resourcespace",
                InvitationManager.DEFAULT_RESOURCE_SPACE);
    }

    private String getDefaultInvitationsSpaceSuffix(XWikiContext context) {
        return context.getWiki().Param("xwiki.invitationmanager.invitationspacesuffix",
                InvitationManager.DEFAULT_INVITATIONS_SPACE_SUFFIX);
    }

    /**
     * @return the name of the document (wiki page) to be used for storing a request of class
     *         <code>joinRequestClass</code> that would allow the specified user to join the
     *         specified space.
     */
    public String getJoinRequestDocumentName(String type, String space, String user, XWikiContext context) {
        if (space == null) {
            space = System.currentTimeMillis() + "";
        }
        if (user == null) {
            user = System.currentTimeMillis() + "";
        }

        user = clearUserName(user);

        return getInvitationSpaceName(space, context) + "." + type + "_" + user;
    }

    private String clearUserName(String user) {
        if (isEmailAddress(user))
            return user.replaceAll("\\.", "_").replaceAll("\\@", "_at_");
        else
            return user.replaceAll("XWiki\\.", "");
    }

    private String getInvitationSpaceName(String space, XWikiContext context) {
        return space + getDefaultInvitationsSpaceSuffix(context);
    }

    /**
     * @return the xwiki class associated with invitations
     */
    public String getInvitationClassName() {
        return INVITATION_CLASS_NAME;
    }

    /**
     * @return the xwiki class associated with invitations
     */
    public String getMembershipRequestClassName() {
        return MEMBERSHIP_REQUEST_CLASS_NAME;
    }

    /**
     * @return the stored invitation uniquely identified by the given space and invitee
     */
    private Invitation getInvitation(String space, String invitee, XWikiContext context) throws XWikiException {
        Invitation invitation = null;
        if (space == null || invitee == null) {
            // skip to the end
        } else if (isEmailAddress(invitee)) {
            String email = invitee.trim();
            String encodedEmail = encodeEmailAddress(email);
            String user = getRegisteredUser(invitee, context);
            invitation = new InvitationImpl(encodedEmail, space, false, this, context);
            if (invitation.isNew() && user != null) {
                invitation = new InvitationImpl(user, space, false, this, context);
            }
            String realInvitee = invitation.getInvitee();
            if (!email.equals(realInvitee) && !user.equals(realInvitee)) {
                invitation = null;
            }
        } else {
            String user = getRegisteredUser(invitee, context);
            if (user != null) {
                String email = "";
                String encodedEmail = encodeEmailAddress(email);
                invitation = new InvitationImpl(user, space, false, this, context);
                if (invitation.isNew()) {
                    invitation = new InvitationImpl(encodedEmail, space, false, this, context);
                }
                String realInvitee = invitation.getInvitee();
                if (!email.equals(realInvitee) && !user.equals(realInvitee)) {
                    invitation = null;
                }
            }
        }
        if (invitation == null) {
            invitation = new InvitationImpl(null, null, false, this, context);
        }
        return invitation;
    }

    /**
     * @return a newly created invitation to be sent to the <code>invitee</code> in order to join
     *         the <code>space</code>
     */
    private Invitation createInvitation(String invitee, String space, XWikiContext context) throws XWikiException {
        return new InvitationImpl(invitee, space, true, this, context);
    }

    /**
     * Creates a custom invitation for the currently logged-in user, from the given one, and then
     * saves it.
     */
    private void customizeInvitation(Invitation invitation, int status, XWikiContext context)
            throws XWikiException {
        Invitation customInvitation = createInvitation(context.getUser(), invitation.getSpace(), context);
        customInvitation.setInviter(invitation.getInviter());
        customInvitation.setMap(invitation.getMap());
        customInvitation.setRequestDate(invitation.getRequestDate());
        customInvitation.setResponseDate(new Date());
        customInvitation.setRoles(invitation.getRoles());
        customInvitation.setStatus(status);
        customInvitation.setOpen(false);
        customInvitation.setText(invitation.getText());
        customInvitation.saveWithProgrammingRights();
    }

    /**
     * @return the stored membership request uniquely identified by the given space and requester
     */
    private MembershipRequest getMembershipRequest(String space, String requester, XWikiContext context)
            throws XWikiException {
        return new MembershipRequestImpl(requester, space, false, this, context);
    }

    /**
     * @return a newly created membership request to be sent by the <code>requester</code> in
     *         order to join the <code>space</code>
     */
    private MembershipRequest createMembershipRequest(String requester, String space, XWikiContext context)
            throws XWikiException {
        return new MembershipRequestImpl(requester, space, true, this, context);
    }

    /**
     * @return the encoded email address to be used when naming the document (wiki page) storing the
     *         invitation to the unregistered user with the given email address
     */
    private String encodeEmailAddress(String emailAddress) {
        return emailAddress.hashCode() + "";
    }

    /**
     * @return a new random code for an invitation
     */
    private String generateInvitationCode() {
        return RandomStringUtils.randomAlphabetic(8).toLowerCase();
    }

    /**
     * Wrapper method for adding a user to a space and to the given roles using the space manager
     */
    private void addMember(String space, String user, List roles, XWikiContext context) throws XWikiException {
        SpaceManager spaceManager = SpaceManagers.findSpaceManagerForSpace(space, context);
        if (!spaceManager.isMember(space, user, context)) {
            spaceManager.addMember(space, user, context);
            if (roles != null && roles.size() > 0) {
                spaceManager.addUserToRoles(space, user, roles, context);
            }
        }
    }

    /**
     * Wrapper method for testing if a user is a member of a space
     */
    private boolean isMember(String space, String user, XWikiContext context) {
        try {
            SpaceManager spaceManager = SpaceManagers.findSpaceManagerForSpace(space, context);
            return spaceManager.isMember(space, user, context);
        } catch (XWikiException e) {
            return false;
        }
    }

    /**
     * Wrapper method for sending a mail using the mail sender plug-in
     */
    private void sendMail(String action, JoinRequest request, String templateDocFullName, XWikiContext context)
            throws XWikiException {
        if (!mailNotification) {
            return;
        }

        VelocityContext vContext = new VelocityContext();
        String spaceName = request.getSpace();
        SpaceManager spaceManager = SpaceManagers.findSpaceManagerForSpace(spaceName, context);
        Space space = spaceManager.getSpace(spaceName, context);
        vContext.put(SPACE_VELOCITY_KEY, space);
        String fromUser = context.getWiki().getXWikiPreference("invitation_email", context);
        if (fromUser == null || fromUser.trim().length() == 0) {
            fromUser = context.getWiki().getXWikiPreference("admin_email", context);
        }
        String[] toUsers = new String[0];
        if (request instanceof Invitation) {
            Invitation invitation = (Invitation) request;
            vContext.put(INVITATION_VELOCITY_KEY, invitation);
            if (JoinRequestAction.SEND.equals(action)) {
                // invitation notification mail
                toUsers = new String[] { invitation.getInvitee() };
            } else {
                // accept or reject invitation mail
                toUsers = new String[] { invitation.getInviter() };
            }
        } else if (request instanceof MembershipRequest) {
            MembershipRequest membershipRequest = (MembershipRequest) request;
            vContext.put(MEMBERSHIP_REQUEST_VELOCITY_KEY, membershipRequest);
            if (JoinRequestAction.SEND.equals(action)) {
                // notify the space administrators of a new membership request pending for approval
                Collection admins = spaceManager.getAdmins(spaceName, context);
                toUsers = (String[]) admins.toArray(new String[admins.size()]);
            } else {
                // create, accept or reject membership request mail
                toUsers = new String[] { membershipRequest.getRequester() };
            }
        }

        if (fromUser == null) {
            throw new InvitationManagerException(InvitationManagerException.MODULE_PLUGIN_INVITATIONMANAGER,
                    InvitationManagerException.ERROR_INVITATION_SENDER_EMAIL_INVALID, "Sender email is invalid");
        }

        boolean toUsersValid = toUsers.length > 0;
        for (int i = 0; i < toUsers.length && toUsersValid; i++) {
            if (!isEmailAddress(toUsers[i])) {
                toUsers[i] = getEmailAddress(toUsers[i], context);
            }
            if (toUsers[i] == null) {
                toUsersValid = false;
            }
        }

        if (!toUsersValid) {
            throw new InvitationManagerException(InvitationManagerException.MODULE_PLUGIN_INVITATIONMANAGER,
                    InvitationManagerException.ERROR_INVITATION_TARGET_EMAIL_INVALID, "Target email is invalid");
        }
        String strToUsers = join(toUsers, ",");

        MailSenderPlugin mailSender = getMailSenderPlugin(context);

        // gets the template doc
        XWikiDocument mailDoc = context.getWiki().getDocument(templateDocFullName, context);
        XWikiDocument translatedMailDoc = mailDoc.getTranslatedDocument(context);

        // puts some generic variables in the velocity rendering context so we can write the
        // template doc almost as a normal document
        vContext.put("xwiki", new XWiki(context.getWiki(), context));
        vContext.put("context", new com.xpn.xwiki.api.Context(context));
        vContext.put("doc", translatedMailDoc);
        vContext.put("space", space);

        try {
            mailSender.sendMailFromTemplate(templateDocFullName, fromUser, strToUsers, null, null,
                    context.getLanguage(), vContext, context);
        } catch (Exception e) {
            throw new InvitationManagerException(InvitationManagerException.MODULE_PLUGIN_INVITATIONMANAGER,
                    InvitationManagerException.ERROR_INVITATION_SENDING_EMAIL_FAILED,
                    "Sending notification email failed", e);
        }
    }

    private static final String join(String[] array, String separator) {
        StringBuffer result = new StringBuffer("");
        if (array.length > 0) {
            result.append(array[0]);
        }
        for (int i = 1; i < array.length; i++) {
            result.append("," + array[i]);
        }
        return result.toString();
    }

    private MailSenderPlugin getMailSenderPlugin(XWikiContext context) throws InvitationManagerException {
        MailSenderPlugin mailSender = (MailSenderPlugin) context.getWiki().getPlugin("mailsender", context);

        if (mailSender == null)
            throw new InvitationManagerException(InvitationManagerException.MODULE_PLUGIN_INVITATIONMANAGER,
                    InvitationManagerException.ERROR_INVITATION_MANAGER_REQUIRES_MAILSENDER_PLUGIN,
                    "Invitation Manager requires the mail sender plugin");

        return mailSender;
    }

    /**
     * @return the wiki name of the registered user with the given
     *         <code>wikiNameOrMailAddress</code>
     */
    private String getRegisteredUser(String wikiNameOrMailAddress, XWikiContext context) {
        if (!isEmailAddress(wikiNameOrMailAddress)) {
            return findUser(wikiNameOrMailAddress, context);
        }
        String email = wikiNameOrMailAddress;
        String sql = "select distinct doc.fullName from XWikiDocument as doc, BaseObject as obj, StringProperty as prop where doc.fullName=obj.name and obj.className = 'XWiki.XWikiUsers' and obj.id=prop.id.id and prop.id.name='email' and prop.value='"
                + email + "'";
        List userList = Collections.EMPTY_LIST;
        try {
            userList = context.getWiki().getStore().search(sql, 1, 0, context);
        } catch (XWikiException e) {
        }
        if (userList.size() > 0) {
            return (String) userList.get(0);
        } else {
            return null;
        }
    }

    /**
     * Helper method for testing if a given string is an email address.
     */
    private boolean isEmailAddress(String str) {
        return str.contains("@");
    }

    /**
     * @return the email address of the given user, provided he is registered
     */
    private String getEmailAddress(String user, XWikiContext context) throws InvitationManagerException {
        try {
            String wikiuser = (user.startsWith("XWiki.")) ? user : "XWiki." + user;

            if (wikiuser == null)
                return null;

            XWikiDocument userDoc = null;
            userDoc = context.getWiki().getDocument(wikiuser, context);

            if (userDoc.isNew())
                return null;

            String email = "";
            try {
                email = userDoc.getObject("XWiki.XWikiUsers").getStringValue("email");
            } catch (Exception e) {
                return null;
            }
            if ((email == null) || (email.equals("")))
                return null;

            return email;
        } catch (Exception e) {
            throw new InvitationManagerException(InvitationManagerException.MODULE_PLUGIN_INVITATIONMANAGER,
                    InvitationManagerException.ERROR_INVITATION_CANNOT_FIND_EMAIL_ADDRESS,
                    "Cannot find email address of user " + user, e);
        }
    }

    private String findUser(String userName, XWikiContext context) {
        userName = userName.trim();
        if (!userName.startsWith("XWiki.")) {
            userName = "XWiki." + userName;
        }
        if (context.getWiki().exists(userName, context))
            return userName;
        else
            return null;
    }

    /**
     * Creates and saves a user profile associated with the given space and the user who made the
     * membership request
     */
    private void createSpaceUserProfile(String spaceName, MembershipRequest request, XWikiContext context)
            throws XWikiException {
        SpaceManager spaceManager = SpaceManagers.findSpaceManagerForSpace(spaceName, context);
        SpaceUserProfile profile = new SpaceUserProfileImpl(request.getRequester(), spaceName, spaceManager,
                context);
        profile.setAllowNotifications("true".equals(request.getMap().get("allowNotifications")));
        profile.setAllowNotificationsFromSelf("true".equals(request.getMap().get("allowNotificationsFromSelf")));
        String profileText = (String) request.getMap().get("profile");
        if (profileText == null) {
            profileText = request.getText();
        }
        if (profileText == null) {
            profileText = "";
        }
        profile.setProfile(profileText);
        profile.saveWithProgrammingRights();
    }

    /**
     * Creates and saves a user profile associated with the given space and the currently logged in
     * user
     */
    private void createSpaceUserProfile(String spaceName, XWikiContext context) throws XWikiException {
        SpaceManager spaceManager = SpaceManagers.findSpaceManagerForSpace(spaceName, context);
        SpaceUserProfile profile = new SpaceUserProfileImpl(context.getUser(), spaceName, spaceManager, context);
        profile.updateProfileFromRequest();
        profile.saveWithProgrammingRights();
    }

    public boolean isWithUserProfiles(XWikiContext context) {
        return context.getWiki().Param("xwiki.invitationmanager.userprofiles", USER_PROFILES_DEFAULT).equals("0")
                ? false
                : true;
    }

    public boolean isMailNotification() {
        return mailNotification;
    }

    public void setMailNotification(boolean mailNotification) {
        this.mailNotification = mailNotification;
    }
}