text:
package org.sakaiproject.site.tool.helper.managegroupsectionrole.impl;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import lombok.Getter;
import lombok.Setter;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.authz.api.AuthzGroup;
import org.sakaiproject.authz.api.AuthzGroupService;
import org.sakaiproject.authz.api.GroupNotDefinedException;
import org.sakaiproject.authz.api.Member;
import org.sakaiproject.authz.api.Role;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.event.cover.EventTrackingService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.site.api.Group;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.site.util.Participant;
import org.sakaiproject.site.util.SiteConstants;
import org.sakaiproject.site.util.SiteGroupHelper;
import org.sakaiproject.site.util.SiteParticipantHelper;
import org.sakaiproject.site.util.GroupHelper;
import org.sakaiproject.sitemanage.api.SiteHelper;
import org.sakaiproject.tool.api.SessionManager;
import org.sakaiproject.tool.api.Tool;
import org.sakaiproject.tool.api.ToolManager;
import org.sakaiproject.tool.api.ToolSession;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserDirectoryService;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.util.RequestFilter;

import uk.org.ponder.messageutil.TargettedMessage;
import uk.org.ponder.messageutil.TargettedMessageList;
import au.com.bytecode.opencsv.CSVReader;
import java.util.Arrays;
import org.sakaiproject.coursemanagement.api.CourseManagementService;
import org.sakaiproject.coursemanagement.api.Section;
import org.sakaiproject.coursemanagement.api.exception.IdNotFoundException;
import uk.org.ponder.messageutil.MessageLocator;

/**
 *
 * @author
 *
 */
public class SiteManageGroupSectionRoleHandler {

	private static final String REQ_ATTR_GROUPFILE = "groupfile";

    /** Our log (commons). */
	private static final Log M_log = LogFactory.getLog(SiteManageGroupSectionRoleHandler.class);

	private List<Member> groupMembers;
    private final GroupComparator groupComparator = new GroupComparator();

    public MessageLocator messageLocator;

    public Site site = null;
    public SiteService siteService = null;
    public AuthzGroupService authzGroupService = null;
    public ToolManager toolManager = null;
    public SessionManager sessionManager = null;
    public ServerConfigurationService serverConfigurationService;
    public CourseManagementService cms = null;
    private List<Group> groups = null;
    public String memberList = "";
    public boolean update = false;
    public boolean done = false;

    public String[] selectedGroupMembers = new String[]{};
    public String[] selectedSiteMembers = new String[]{};

    // selected rosters for autocreate groups
    public Map<String, Boolean> selectedRosters = new HashMap<>();

    // selected roles for autocreate groups
    public Map<String, Boolean> selectedRoles = new HashMap<>();

    private static final int OPTION_ASSIGN_BY_ROLES_OR_ROSTER = 1;
    private static final int OPTION_ASSIGN_RANDOM = 2;
    public int optionAssign = OPTION_ASSIGN_BY_ROLES_OR_ROSTER;
    public boolean groupSplit = true;
    public String numToSplitGroup = "";
    public String numToSplitUser = "";
    public String groupTitleGroup = "";
    public String groupTitleUser = "";

    // SAK-29373
    public int rosterOptionAssign = OPTION_ASSIGN_BY_ROLES_OR_ROSTER;
    public boolean rosterGroupSplit = true;
    public String rosterNumToSplitGroup = "";
    public String rosterNumToSplitUser = "";
    public String rosterGroupTitleGroup = "";
    public String rosterGroupTitleUser = "";

    private final String HELPER_ID = "sakai.tool.helper.id";
    private final String GROUP_DELETE = "group.delete";
    private final String SITE_RESET = "group.reset";

    public String joinableSetName = "";
    public String joinableSetNameOrig = "";
    public String joinableSetNumOfGroups = "";
    public String joinableSetNumOfMembers = "";
    public boolean allowPreviewMembership = false;
    public boolean allowViewMembership = false;
    public boolean unjoinable = false;
    public boolean unjoinableOrig = false;
    private int groupsCreated = 0;
    public List<String> pendingGroupTitles = new ArrayList<>();

    // Tool session attribute name used to schedule a whole page refresh.
    public static final String ATTR_TOP_REFRESH = "sakai.vppa.top.refresh";

    // SAK-23016 - added CSV types from http://filext.com/file-extension/CSV
    private static final String[] CSV_MIME_TYPES = {
        "application/csv",
        "application/excel",
        "application/vnd.ms-excel",
        "application/vnd.msexcel",
        "text/anytext",
        "text/comma-separated-values",
        "text/csv"
    };

	public TargettedMessageList messages;
	public void setMessages(TargettedMessageList messages) {
		this.messages = messages;
	}

    private void resetTargettedMessageList()
    {
    	this.messages = new TargettedMessageList();
    }

	private final org.sakaiproject.authz.api.GroupProvider groupProvider = (org.sakaiproject.authz.api.GroupProvider) ComponentManager.get(org.sakaiproject.authz.api.GroupProvider.class);

	// the group title
	private String id;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	// group title
	private String title;

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	// group description
	private String description;

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	// for those to be deleted groups
	public String[] deleteGroupIds;

	/**
	 * reset the variables
	 */
	public void resetParams()
	{
        // SAK-29645 - don't reset the params if an error message was posted (preserve user input)
        if( messages.size() == 0 )
        {
            id = "";
            title = "";
            description ="";
            deleteGroupIds=new String[]{};
            selectedGroupMembers = new String[]{};
            selectedSiteMembers = new String[]{};
            selectedRosters = new HashMap<>();
            selectedRoles = new HashMap<>();
            memberList = new String();

            optionAssign=OPTION_ASSIGN_BY_ROLES_OR_ROSTER;
            groupSplit = true;
            numToSplitUser = "";
            numToSplitGroup = "";
            groupTitleUser = "";
            groupTitleGroup = "";

            // SAK-29373
            rosterOptionAssign = OPTION_ASSIGN_BY_ROLES_OR_ROSTER;
            rosterGroupSplit = true;
            rosterNumToSplitUser = "";
            rosterNumToSplitGroup = "";
            rosterGroupTitleUser = "";
            rosterGroupTitleGroup = "";

            importedGroups = null;

            joinableSetName = "";
            joinableSetNameOrig = "";
            unjoinable = false;
            unjoinableOrig = false;
            pendingGroupTitles.clear();
            resetJoinableSetGroupParams();
        }
	}

    /**
     * Utility method to clear our the params for generating additional groups for a joinable set
     */
    public void resetJoinableSetGroupParams()
    {
        joinableSetNumOfMembers = "";
        allowPreviewMembership = false;
        allowViewMembership = false;
        joinableSetNumOfGroups = "";
        groupsCreated = 0;
    }

    /**
     * Gets the groups for the current site
     * @return Map of groups (id, group)
     */
    public List<Group> getGroups() {
        if (site == null) {
            init();
        }
        if (update) {
            groups = new ArrayList<>();
            if (site != null)
            {
                // only show groups created by WSetup tool itself
    			Collection allGroups = (Collection) site.getGroups();
    			for (Iterator gIterator = allGroups.iterator(); gIterator.hasNext();) {
    				Group gNext = (Group) gIterator.next();
    				String gProp = gNext.getProperties().getProperty(
    						Group.GROUP_PROP_WSETUP_CREATED);
    				if (gProp != null && gProp.equals(Boolean.TRUE.toString())) {
    					groups.add(gNext);
    				}
    			}
            }
        }
        Collections.sort(groups, groupComparator);
        return groups;
    }

    /**
     * Gets the rosters for the current site excluding the group
     * @param group the group to be excluded from the results
     * @return List of roster ids
     */
    public List<String> getSiteRosters(Group group) {
        if (site == null) {
            init();
        }
        List<String> providerIds = null;

        if (update) {
            providerIds = new ArrayList<>();
            if (site != null)
            {
                // get all provider ids
            	Set pIds = authzGroupService.getProviderIds(siteService.siteReference(site.getId()));
            	providerIds.addAll(pIds);
            	if (group != null)
            	{
            		Set groupPIds = authzGroupService.getProviderIds(siteService.siteGroupReference(site.getId(), group.getId()));
            		providerIds.removeAll(groupPIds);
            	}
            }
        }
        return providerIds;
    }

    /**
     * Gets the rosters for the group
     * @param g the group for which rosters are being requested
     * @return List of roster ids
     */
    public List<String> getGroupRosters(Group g) {

        List<String> providerIds = null;

        if (update) {
            providerIds = new ArrayList<>();
            if (g != null)
            {

                // get all provider ids
            	Set pIds = authzGroupService.getProviderIds(siteService.siteGroupReference(site.getId(), g.getId()));
            	providerIds.addAll(pIds);
            }
        }
        return providerIds;
    }

    /**
     * Get the user facing label text for a given roster ID (for auto groups UI).
     * The label will be in the format of "<rosterTitle> (<rosterID>)"
     * @param rosterID the internal ID of the roster
     * @return the user facing label for the given roster
     */
    public String getRosterLabel( String rosterID )
    {
        String label = rosterID;
        try
        {
            Section s = cms.getSection( rosterID );
            if( s != null )
            {
                label = StringUtils.defaultIfBlank(s.getTitle(), rosterID);
            }
        }
        catch( IdNotFoundException ex )
        {
            M_log.debug( this + ".getRosterLabel: no section found for " + rosterID, ex );
        }

        return label;
    }

    /**
     * Gets the roles for the current site excluding the group
     * @param group the group to be excluded from the results
     * @return Map of groups (id, group)
     */
    public List<Role> getSiteRoles(Group group) {
        if (site == null) {
            init();
        }
        List<Role> roles = null;

        if (update) {
            roles = new ArrayList<>();
            if (site != null)
            {
                // get the authz group
            	String siteReference = siteService.siteReference(site.getId());
            	try
            	{
            		AuthzGroup siteGroup = authzGroupService.getAuthzGroup(siteReference);
            		roles.addAll(siteGroup.getRoles());
            	}
            	catch (GroupNotDefinedException e)
            	{
            		M_log.debug(this + ".getRoles: no authzgroup found for " + siteReference, e);
            	}

            	if (group != null)
            	{
            		String roleProviderId = group.getProperties().getProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID);
	            	Collection<String> groupProvidedRoles = SiteGroupHelper.unpack(roleProviderId);
	            	for(String role: groupProvidedRoles)
	            	{
	            		roles.remove(group.getRole(role));
	            	}
            	}
            }
        }
        return roles;
    }

    /**
     * Gets the role ids for the current site
     * @return Map of groups (id, group)
     */
    public List<String> getSiteRoleIds() {
    	List<String> rv = new ArrayList<>();
        List<Role> roles = getSiteRoles(null);
        if (roles != null)
        {
        	for(Role r:roles)
        	{
        		rv.add(r.getId());
        	}
        }
        return rv;
    }

    public boolean isUserFromProvider(String userEId, String userId, Group g, List<String> rosterIds, List<String> roleIds)
    {
    	boolean rv = false;

    	// check roster first
    	if (rosterIds != null)
    	{
	    	for (int i = 0; !rv && i < rosterIds.size(); i++)
	    	{
	    		if (groupProvider != null)
	    		{
		    		String providerId = rosterIds.get(i);
			    	Map userRole = groupProvider.getUserRolesForGroup(providerId);
			    	if (userRole.containsKey(userEId))
			    	{
			    		rv =  true;
			    	}
	    		}
	    	}
    	}

    	// check role next
    	if (!rv && roleIds != null)
    	{
    		for (int i = 0; !rv && i < roleIds.size(); i++)
	    	{
    			String roleId = roleIds.get(i);
		    	if (g.getUserRole(userId).getId().equals(roleId))
		    	{
		    		rv =  true;
		    	}
	    	}
    	}

    	return rv;
    }

    /**
     * Gets the roles for the group
     * @param g the group for which roles are being requested
     * @return Map of groups (id, group)
     */
    public List<String> getGroupProviderRoles(Group g) {
        List<String> rv = null;

        if (update) {
            rv = new ArrayList<>();
            if (g != null)
            {
                // get the authz group
            	String roleProviderId = g.getProperties().getProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID);
            	if (roleProviderId != null)
            	{
            		if (groupProvider != null)
            		{
	            		String[] roleStrings = groupProvider.unpackId(roleProviderId);
	            		rv.addAll( Arrays.asList( roleStrings ) );
            		}
            	}
            }
        }
        return rv;
    }

    /**
     * Initialization method, just gets the current site in preparation for other calls
     *
     */
    public void init() {
        if (site == null) {
            String siteId = null;
            try {
                siteId = sessionManager.getCurrentToolSession()
                        .getAttribute(HELPER_ID + ".siteId").toString();
            }
            catch (java.lang.NullPointerException npe) {
                // Site ID wasn't set in the helper call!!
                M_log.warn( npe );
            }

            if (siteId == null) {
                siteId = toolManager.getCurrentPlacement().getContext();
            }

            try {
                site = siteService.getSite(siteId);
                // allow update site or group membership
                update = siteService.allowUpdateSite(site.getId()) || siteService.allowUpdateGroupMembership(site.getId());

            } catch (IdUnusedException e) {
                // The siteId we were given was bogus
                M_log.warn( e );
            }
        }
        title = "";

        if (groupMembers == null)
        {
        	groupMembers = new ArrayList<>();
        }
    }

    /**
     * Wrapper around siteService to save a site
     * @param site
     * @throws IdUnusedException
     * @throws PermissionException
     */
    public void saveSite(Site site) throws IdUnusedException, PermissionException {
        siteService.save(site);
    }

    public List<Participant> getSiteParticipant(Group group)
    {
    	List<Participant> rv = new ArrayList<>();
    	if (site != null)
    	{
    		String siteId = site.getId();

    		List<String> providerCourseList = SiteParticipantHelper.getProviderCourseList(siteId);
    		Collection<Participant> rvCopy = SiteParticipantHelper.prepareParticipants(siteId, providerCourseList);

    		// check with group attendents
    		if (group != null)
    		{
    			// need to remove those inside group already
	    		for(Participant p:rvCopy)
	    		{
	    			if (p.getUniqname() != null && group.getMember(p.getUniqname()) == null)
	    			{
	    				rv.add(p);
	    			}
	    		}
    		}
    		else
    		{
    			// if the group is null, add all site members
    			rv.addAll(rvCopy);
    		}
    	}

    	return rv;
    }

    public List<Member> getGroupParticipant()
    {

    	return groupMembers;
    }

    /**
     * Allows the Cancel button to return control to the tool calling this helper
     *
     * @return status
     */
    public String processCancel() {
    	// reset the warning messages
    	resetTargettedMessageList();

        ToolSession session = sessionManager.getCurrentToolSession();
        session.setAttribute(ATTR_TOP_REFRESH, Boolean.TRUE);

        return "done";
    }

    /**
     * Cancel out of the current action and go back to main view
     *
     * @return status
     */
    public String processBack() {
    	// reset the warning messages
    	resetTargettedMessageList();

    	return "cancel";
    }

    public String reset() {
        try {
            siteService.save(site);
            EventTrackingService.post(
                EventTrackingService.newEvent(SITE_RESET, "/site/" + site.getId(), false));

        }
        catch (IdUnusedException | PermissionException e) {
            M_log.warn( e );
        }

        return "";
    }

    /**
     * Adds a new group to the current site, or edits an existing group
     * @return "success" if group was added/edited, null if something went wrong
     */
    public String processAddGroup () {

    	// reset the warning message
    	resetTargettedMessageList();

        Group group;

        // those added user into group
        List<String> addedGroupMember = new ArrayList<>();

        // those deleted user from group
        List<String> removedGroupMember = new ArrayList<>();

        id = StringUtils.trimToNull(id);

        title = StringUtils.trimToNull(title);
    	if (title == null)
    	{
    		messages.addMessage(new TargettedMessage("editgroup.titlemissing",new Object[]{}, TargettedMessage.SEVERITY_ERROR));
    		return null;
    	}
    	else if (title.length() > SiteConstants.SITE_GROUP_TITLE_LIMIT)
    	{
    		messages.addMessage(new TargettedMessage("site_group_title_length_limit",new Object[] { String.valueOf(SiteConstants.SITE_GROUP_TITLE_LIMIT) }, TargettedMessage.SEVERITY_ERROR));
    		return null;
    	}
    	else
    	{
            String sameTitleGroupId = GroupHelper.getSiteGroupByTitle(site, title);
            // "id" will be null if adding a new group, otherwise it will be the id of the group being edited
            if (!sameTitleGroupId.isEmpty() && (id == null || !sameTitleGroupId.equals(id)))
            {
                messages.addMessage(new TargettedMessage("group.title.same", null, TargettedMessage.SEVERITY_ERROR));
                return null;
            }
    	}

    	int joinableSetNumOfMembersInt;
    	if(joinableSetName != null && !"".equals(joinableSetName.trim())){
    		if(joinableSetNumOfMembers == null || "".equals(joinableSetNumOfMembers)){
    			messages.addMessage(new TargettedMessage("maxMembers.empty.alert","num-groups"));
    			return null;
    		}else{
    			try{
    				joinableSetNumOfMembersInt = Integer.parseInt(joinableSetNumOfMembers);
    				if(joinableSetNumOfMembersInt <= 0){
        				messages.addMessage(new TargettedMessage("maxMembers.zero.alert","num-max-members"));
            			return null;
        			}
    			}catch (Exception e) {
    				messages.addMessage(new TargettedMessage("maxMembers.empty.alert","num-max-members"));
    				return null;
    			}
    		}
    	}

		if (id != null)
		{
			// editing existing group
			group = site.getGroup(id);
		}
		else
		{
			// adding a new group
	        group= site.addGroup();
	        group.getProperties().addProperty(Group.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString());
		}

		if (group != null)
		{
			group.setTitle(title);
            group.setDescription(description);
            group.getProperties().addProperty(Group.GROUP_PROP_VIEW_MEMBERS, Boolean.toString(allowViewMembership));
            if(joinableSetName != null && !"".equals(joinableSetName.trim())){
            	group.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_SET, joinableSetName);
            	group.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_SET_MAX, joinableSetNumOfMembers);
            	group.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_SET_PREVIEW,Boolean.toString(allowPreviewMembership));
            	group.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_UNJOINABLE, Boolean.toString(unjoinable));
            }else{
            	group.getProperties().removeProperty(Group.GROUP_PROP_JOINABLE_SET);
            	group.getProperties().removeProperty(Group.GROUP_PROP_JOINABLE_SET_MAX);
            	group.getProperties().removeProperty(Group.GROUP_PROP_JOINABLE_SET_PREVIEW);
            	group.getProperties().removeProperty(Group.GROUP_PROP_JOINABLE_UNJOINABLE);
            }

            boolean found;
            // remove those no longer included in the group
			Set members = group.getMembers();
			String[] membersSelected = (memberList != null && memberList.length() > 0) ? memberList.split("##"):new String[0];
			for (Iterator iMembers = members.iterator(); iMembers
					.hasNext();) {
				found = false;
				String mId = ((Member) iMembers.next()).getUserId();
				for (int i = 0; !found && i < membersSelected.length; i++)
				{
					if (mId.equals(membersSelected[i])) {
						found = true;
					}

				}
				if (!found) {
					group.removeMember(mId);
					removedGroupMember.add("uid=" + mId + ";groupId=" + group.getId());
				}
			}

			// add those selected members
			List<String> siteRosters = getSiteRosters(null);
			List<String> siteRoles = getSiteRoleIds();
			List<String> selectedRosters = new ArrayList<>();
			List<String> selectedRoles = new ArrayList<>();
            for( String memberId : membersSelected )
            {
                if (siteRosters.contains(memberId))
                {
                    // this is a roster
                    selectedRosters.add(memberId);
                    // TODO: log event for each individual user?
                }
                else if (siteRoles.contains(memberId))
                {
                    // this is a role
                    Set roleUsers = site.getUsersHasRole(memberId);
                    for (Iterator iRoleUsers = roleUsers.iterator(); iRoleUsers.hasNext();)
                    {
                        String roleUserId = (String) iRoleUsers.next();
                        Member member = site.getMember(roleUserId);
                        group.addMember(roleUserId, memberId, member.isActive(), false);
                        addedGroupMember.add("uid=" + roleUserId + ";role=" + member.getRole().getId() + ";active=" + member.isActive() + ";provided=false;groupId=" + group.getId());
                    }
                    selectedRoles.add(memberId);
                }
                else
                {
                    // normal user id
                    memberId = StringUtils.trimToNull(memberId);
                    if (memberId != null && group.getUserRole(memberId) == null) {
                        Role r = site.getUserRole(memberId);
                        Member m = site.getMember(memberId);
                        Role memberRole = m != null ? m.getRole() : null;
                        // for every member added through the "Manage
                        // Groups" interface, he should be defined as
                        // non-provided
                        // get role first from site definition.
                        // However, if the user is inactive, getUserRole would return null; then use member role instead
                        String roleString = r != null ? r.getId(): memberRole != null? memberRole.getId() : "";
                        boolean active = m != null ? m.isActive() : true;
                        group.addMember(memberId, roleString, active,false);
                        addedGroupMember.add("uid=" + memberId + ";role=" + roleString + ";active=" + active + ";provided=false;groupId=" + group.getId());
                    }
                }
            }
			if (!selectedRosters.isEmpty())
			{
				//since RSF doesn't like "."s, they have been escaped.  Now unescape them
				for(String s : selectedRoles){
					s = s.replaceAll("-_p_-", ".");
				}
				// set provider id
				group.setProviderGroupId(getProviderString(selectedRosters));
			}
			else
			{
				// clear the provider id
				group.setProviderGroupId(null);
			}
			if (!selectedRoles.isEmpty())
			{
				// pack the role provider id and add to property
    			group.getProperties().addProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID, getProviderString(selectedRoles));
			}
			else
			{
				// clear the role provider id
				group.getProperties().removeProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID);
			}

    		// save the changes
    		try
    		{
    			siteService.save(site);

    			// post event about the participant update
				EventTrackingService.post(EventTrackingService.newEvent(SiteService.SECURE_UPDATE_GROUP_MEMBERSHIP, group.getId(),true));

				if (serverConfigurationService.getBoolean(SiteHelper.WSETUP_TRACK_USER_MEMBERSHIP_CHANGE, false))
				{
					// added members
					for(String addedMemberString : addedGroupMember)
					{
						// an event for each individual member add
						EventTrackingService.post(EventTrackingService.newEvent(SiteService.EVENT_USER_GROUP_MEMBERSHIP_ADD, addedMemberString, true/*update event*/));
					}

					// removed members
					for(String removedMemberString : removedGroupMember)
					{
						// an event for each individual member remove
						EventTrackingService.post(EventTrackingService.newEvent(SiteService.EVENT_USER_GROUP_MEMBERSHIP_REMOVE, removedMemberString, true/*update event*/));

					}
				}
    			// reset the form params
    			resetParams();
	        }
	        catch (IdUnusedException | PermissionException e) {
	        	M_log.error(this + ".processAddGroup: cannot find site " + site.getId(), e);
	            return null;
	        }
    	}

        return "success";
    }

    public String processConfirmGroupDelete()
    {

    	// reset the warning messages
    	resetTargettedMessageList();

    	if (deleteGroupIds == null || deleteGroupIds.length == 0)
    	{
    		// no group chosen to be deleted
    		M_log.debug(this + ".processConfirmGroupDelete: no group chosen to be deleted.");
    		messages.addMessage(new TargettedMessage("delete_group_nogroup","no group chosen"));
    		return null;
    	}
    	else
    	{
    		List<Group> groups = new ArrayList<>();

            for( String groupId : deleteGroupIds )
            {
                try
                {
                    Group g = site.getGroup(groupId);
                    groups.add(g);
                }
                catch (Exception e)
                {
                    M_log.error( e );
                }
            }
	    	return "confirm";
    	}
    }

    public String processDeleteGroups()
    {
    	// reset the warning messages
    	resetTargettedMessageList();

    	if (site != null)
    	{
            for( String groupId : deleteGroupIds )
            {
                Group g = site.getGroup(groupId);
                if (g != null) {
                    site.removeGroup(g);
                }
            }
			try {
				siteService.save(site);
			} catch (IdUnusedException e) {
				messages.addMessage(new TargettedMessage("editgroup.site.notfound.alert","cannot find site"));
				M_log.error(this + ".processDeleteGroups: Problem of saving site after group removal: site id =" + site.getId(), e);
			} catch (PermissionException e) {
				messages.addMessage(new TargettedMessage("editgroup.site.permission.alert","not allowed to find site"));
				M_log.error(this + ".processDeleteGroups: Permission problem of saving site after group removal: site id=" + site.getId(), e);
			}

	    }
    	return "success";
    }

    public String processCancelDelete()
    {
    	// reset the warning messages
    	resetTargettedMessageList();

    	return "cancel";
    }

    /**
     * SAK-29373 - Common validation algorithm for both roster and role based random groups
     *
     * @param option flag denoting split by random options, or create group(s) for roster and/or role (1:1)
     * @param isGroupSplit true = split by number of groups, false = split by number of users per group
     * @param numToSplitForGroups the number of groups requested
     * @param numToSplitForUsers the number of users per group requested
     * @param groupTitleForGroups title requested for split by groups
     * @param groupTitleForUsers title requested for split by number of users per group
     * @return 0 if not for random groups, -1 if for random groups and validation fails. Otherwise, returns the
     * integer value of the number of groups or number of users per group requested.
     */
    private int validateAutoGroupsFields( int option, boolean isGroupSplit, String numToSplitForGroups, String numToSplitForUsers,
                                          String groupTitleForGroups, String groupTitleForUsers)
    {
        int intToSplit = 0;
        if( OPTION_ASSIGN_RANDOM == option )
        {
            String numToSplit = isGroupSplit ? numToSplitForGroups : numToSplitForUsers;
            String groupTitle = isGroupSplit ? groupTitleForGroups : groupTitleForUsers;
            if( numToSplit == null )
            {
                if( isGroupSplit )
                {
                    messages.addMessage( new TargettedMessage( "numToSplit.group.empty.alert", "numToSplit" ) );
                }
                else
                {
                    messages.addMessage( new TargettedMessage( "numToSplit.user.empty.alert", "numToSplit" ) );
                }
                return -1;
            }
            else
            {
                try
                {
                    intToSplit = Integer.parseInt( numToSplit );
                    if( intToSplit <= 0 )
                    {
                        return addAppropriateNotNumberError( isGroupSplit );
                    }
                }
                catch( NumberFormatException ex )
                {
                    return addAppropriateNotNumberError( isGroupSplit );
                }
            }

            if( groupTitle == null || "".equals( groupTitle ) )
            {
                messages.addMessage( new TargettedMessage( "groupTitle.empty.alert", "groupTitle" ) );
                return -1;
            }
        }

        return intToSplit;
    }

     /**
     * Add the appropriate 'is not a number' error to the UI
     *
     * @param isGroupSplit true for split on # of groups, false for split on # of users per group
     * @return -1 indicating validation failure
     */
    private int addAppropriateNotNumberError( boolean isGroupSplit )
    {
        if( isGroupSplit )
        {
            messages.addMessage( new TargettedMessage( "numToSplit.group.notanumber.alert", "numToSplit" ) );
        }
        else
        {
            messages.addMessage( new TargettedMessage( "numToSplit.user.notanumber.alert", "numToSplit" ) );
        }
        return -1;
    }

    /**
     * auto create group(s) based on selected roster(s) or role(s)
     *
     * @return status
     */
    public String processAutoCreateGroup() {
        // reset the warning messages
        resetTargettedMessageList();

        // Check if fields are valid
        int intToSplit = validateAutoGroupsFields( optionAssign, groupSplit, numToSplitGroup, numToSplitUser, groupTitleGroup, groupTitleUser );
        int rosterIntToSplit = validateAutoGroupsFields( rosterOptionAssign, rosterGroupSplit, rosterNumToSplitGroup, rosterNumToSplitUser, rosterGroupTitleGroup, rosterGroupTitleUser );
        if( intToSplit == -1 || rosterIntToSplit == -1 )
        {
            return null;
        }

        List<String> rosterList = new ArrayList<>();
        if( selectedRosters != null )
        {
            for( String roster : selectedRosters.keySet() )
            {
                if (Boolean.TRUE.equals(selectedRosters.get(roster)))
                {
                    // RSF doesn't like periods, so these have been escaped; now unescape them
                    roster = roster.replaceAll("-_p_-", ".");
                    rosterList.add(roster);
                }
            }
        }

        List<String> roleList = new ArrayList<>();
        if( selectedRoles != null )
        {
            for( String role : selectedRoles.keySet() )
            {
                if (Boolean.TRUE.equals(selectedRoles.get(role)))
                {
                    // selected role
                    roleList.add(role);
                }
            }
        }

        if (rosterList.isEmpty() && roleList.isEmpty())
        {
            // nothing selected, generate alert
            messages.addMessage(new TargettedMessage("group.autocreate.selectrosterorrole","Please select at lease one roster or role."));
        }
        else
        {
            // Roster based
            if (!rosterList.isEmpty())
            {
                // SAK-29373
                if( OPTION_ASSIGN_RANDOM == rosterOptionAssign )
                {
                    createRandomGroupsForRoster( rosterList.get( 0 ), rosterIntToSplit );
                }
                else
                {
                    for (String roster:rosterList)
                    {
                        Group group = site.addGroup();
                        group.getProperties().addProperty(Group.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString());
                        group.setProviderGroupId(roster);

                        String groupTitle = truncateGroupTitle( getRosterLabel( roster ) + " " + messageLocator.getMessage( "group.autocreate.section.postfix" ) );
                        group.setTitle(groupTitle);
                    }
                }
            }

            // role based
            if (!roleList.isEmpty())
            {
                if(OPTION_ASSIGN_BY_ROLES_OR_ROSTER == optionAssign){
                    for(String role:roleList)
                    {
                        Group group = site.addGroup();
                        // make the provider id as of SITEID_ROLEID
                        //group.setProviderGroupId(site.getId() + "_" + role);
                        group.getProperties().addProperty(Group.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString());
                        group.getProperties().addProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID, role);

                        String groupTitle = truncateGroupTitle(role);
                        group.setTitle(groupTitle);

                        // get the authz group
                        String siteReference = siteService.siteReference(site.getId());
                        try
                        {
                            AuthzGroup siteGroup = authzGroupService.getAuthzGroup(siteReference);
                            Set<String> usersHasRole = siteGroup.getUsersHasRole(role);
                            if (usersHasRole != null)
                            {
                                for( String userId : usersHasRole )
                                {
                                    Member member = site.getMember(userId);
                                    group.addMember(userId, role, member.isActive(), false);
                                }
                            }
                        }
                        catch (GroupNotDefinedException e)
                        {
                            M_log.debug(this + ".processAutoCreateGroup: no authzgroup found for " + siteReference, e);
                        }
                    }
                }else{
                    createRandomGroupsForRole( roleList.get( 0 ), intToSplit );
                }
            }

            // save the changes
            try
            {
                siteService.save(site);
                // reset the form params
                resetParams();
            }
            catch (IdUnusedException | PermissionException e) {
                M_log.error(this + ".processAutoCreateGroup: cannot find site " + site.getId(), e);
                return null;
            }
        }

        return "done";
    }

    /**
     * SAK-29373 - Create random groups of users from the given roster.
     * This could be random number of users in specified number of groups,
     * or vice versa.
     *
     * @param providerID the provider ID selected
     * @param unit the number of groups or users per group requested
     */
    private void createRandomGroupsForRoster( String providerID, int unit )
    {
        String groupTitle = rosterGroupSplit ? rosterGroupTitleGroup: rosterGroupTitleUser;
        if( StringUtils.isNotBlank( groupTitle ) && StringUtils.isNotBlank( providerID ) )
        {
            Set<String> userSet = new HashSet<>();
            List<AuthzGroup> realms = authzGroupService.getAuthzGroups( providerID, null );
            for( AuthzGroup realm : realms )
            {
                if( providerID.equals( realm.getProviderGroupId() ) )
                {
                    Set<Member> members = realm.getMembers();
                    for( Member member : members )
                    {
                        userSet.add( member.getUserId() );
                    }
                }
            }

            createRandomGroups( rosterGroupSplit, new ArrayList<>( userSet ), groupTitle, unit );
        }
    }

    /**
     * Common algorithm called to create random groups.
     *
     * @param isGroupSplit true = split by # of groups, false = split by # of users per group
     * @param userIDs list of user IDs to include in the groups
     * @param groupTitle the title prefix of the groups requested
     * @param unit the amount of groups or users per group requested
     */
    private void createRandomGroups( boolean isGroupSplit, List<String> userIDs, String groupTitle, int unit )
    {
        int numOfGroups = -1;
        int numOfUsersPerGroup = -1;
        int totalNumOfUsers = userIDs.size();

        // Determine number of users per group and number of groups to create
        if( isGroupSplit )
        {
            numOfGroups = unit > totalNumOfUsers ? totalNumOfUsers : unit;
            if( numOfGroups > 0 )
            {
                numOfUsersPerGroup = totalNumOfUsers / numOfGroups;
            }
        }
        else
        {
            numOfUsersPerGroup = unit > totalNumOfUsers ? totalNumOfUsers : unit;
            if( numOfUsersPerGroup > 0 )
            {
                numOfGroups = totalNumOfUsers / numOfUsersPerGroup;
            }
        }

        int groupCount = 0;
        List<Group> groupList = new ArrayList<>();
        while( groupCount < numOfGroups )
        {
            // Create the group
            Group group = site.addGroup();
            group.getProperties().addProperty( Group.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString() );
            group.setTitle( groupTitle + "-" + (groupCount + 1) );

            int userCount = 0;
            while( userCount < numOfUsersPerGroup && userIDs.size() > 0 )
            {
                // Pick a random user
                int index = (int)(Math.random() * (userIDs.size() - 1));
                String userID = userIDs.get( index );
                Member member = site.getMember( userID );

                // Add the user to the group
                group.addMember( userID, member.getRole().getId(), member.isActive(), false );
                userIDs.remove( index );
                userCount++;
            }

            groupCount++;
            groupList.add( group );
        }

        // All the groups have been created, but there are some users still left to be assigned (remainders)
        while( userIDs.size() > 0 )
        {
            // Pick a random user
            int userIndex = (int)(Math.random() * (userIDs.size() - 1));
            String userID = userIDs.get( userIndex );

            // Pick a random group
            int groupIndex = (int)(Math.random() * (groupList.size() - 1));
            Group group = groupList.get( groupIndex );

            // Add the user to the group
            Member member = site.getMember( userID );
            group.addMember( userID, member.getRole().getId(), member.isActive(), false );
            userIDs.remove( userIndex );
        }
    }

    /**
     * Create random groups of users from the given role.
     * This could be random number of users in specified number of groups,
     * or vice versa.
     *
     * @param role the desired role to create groups for
     * @param unit the number of groups or users per group requested
     */
    private void createRandomGroupsForRole( String role, int unit )
    {
        String groupTitle = groupSplit ? groupTitleGroup : groupTitleUser;
        if( StringUtils.isNotBlank( groupTitle ) && StringUtils.isNotBlank( role ) )
        {
            List<String> usersList = new ArrayList<>();
            String siteReference = siteService.siteReference( site.getId() );

            try
            {
                // Build the user ID list
                AuthzGroup siteGroup = authzGroupService.getAuthzGroup( siteReference );
                Set<String> usersWithRole = siteGroup.getUsersHasRole( role );
                if( usersWithRole != null )
                {
                    for( String userID : usersWithRole )
                    {
                        usersList.add( userID );
                    }
                }
            }
            catch( GroupNotDefinedException ex )
            {
                M_log.debug( this + ".processAutoCreateGroup: no authzgroup found for " + siteReference, ex );
            }

            createRandomGroups( groupSplit, usersList, groupTitle, unit );
        }
    }

    /**
     * check whether the title string is within length limit, truncate it if necessary
     * @param oTitle
     * @return
     */
	private String truncateGroupTitle(String oTitle) {
		if (oTitle.length() > SiteConstants.SITE_GROUP_TITLE_LIMIT)
		{
			oTitle = oTitle.substring(0, SiteConstants.SITE_GROUP_TITLE_LIMIT);
		}
		return oTitle.trim();
	}

	/**
	 * Return a single string representing the provider id list
	 * @param idsList
	 */
	private String getProviderString(List<String> idsList)
	{
		return SiteGroupHelper.pack(idsList);
	}

    /**
     * Removes a group from the site
     *
     * @param groupId
     * @return title of page removed
     * @throws IdUnusedException
     * @throws PermissionException
     */
    public String removeGroup(String groupId)
                            throws IdUnusedException, PermissionException {
        Group group = site.getGroup(groupId);
        site.removeGroup(group);
        saveSite(site);

        EventTrackingService.post(
            EventTrackingService.newEvent(GROUP_DELETE, "/site/" + site.getId() +
                                          "/group/" + group.getId(), false));

        return group.getTitle();
    }

	public String[] getDeleteGroupIds() {
		return deleteGroupIds;
	}

	public List<Group> getSelectedGroups()
	{
		List<Group> rv = new ArrayList<>();
		if (deleteGroupIds != null && deleteGroupIds.length > 0 && site != null)
		{
            for( String groupId : deleteGroupIds )
            {
                try
                {
                    Group g = site.getGroup(groupId);
                    rv.add(g);
                }
                catch (Exception e)
                {
                    M_log.debug(this + ":getSelectedGroups: cannot get group with id " + groupId);
                }
            }
		}
		return rv;
	}

	public void setDeleteGroupIds(String[] deleteGroupIds) {
		this.deleteGroupIds = deleteGroupIds;
	}

    /**
     * Gets the current tool
     * @return Tool
     */
    public Tool getCurrentTool() {
        return toolManager.getCurrentTool();
    }

    /**
     * check whether there is already a group within the site containing the roster id
     * @param rosterId
     * @return
     */
    public boolean existRosterGroup(String rosterId)
    {
    	boolean rv = false;

    	Collection<Group> groups = site.getGroups();

    	for(Group group:groups)
    	{
    		// check if there is one group with this roster id already
    		String groupWSetupCreated = group.getProperties().getProperty(Group.GROUP_PROP_WSETUP_CREATED);
			if (groupWSetupCreated != null && groupWSetupCreated.equalsIgnoreCase(Boolean.TRUE.toString()))
			{
				if (group.getProviderGroupId() != null && group.getProviderGroupId().equals(rosterId))
				{
					rv = true;
					break;
				}
			}
    	}

    	return rv;
    }

    /**
     * Check whether there is already a group within the site containing the role id
     * @param roleId This role to check the site groups against. eg: access.
     * @return <code>true</code> if this a group for this role already exists.
     */
    public boolean existRoleGroup(String roleId)
    {
    	boolean rv = false;

    	Collection<Group> groups = site.getGroups();

    	for(Group group:groups)
    	{
    		// check if there is one group with this roster id already
    		String groupWSetupCreated = group.getProperties().getProperty(Group.GROUP_PROP_WSETUP_CREATED);
			if (groupWSetupCreated != null && groupWSetupCreated.equalsIgnoreCase(Boolean.TRUE.toString()))
			{
				String groupRole = group.getProperties().getProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID);
				if (groupRole != null && groupRole.equals(roleId))
				{
					rv = true;
					break;
				}
			}
    	}

    	return rv;
    }

    /**
     * Find all users in the current site who are not a member of any of a set's
     * given groups
     * @param setGroups all existing groups for the set
     * @return a list of all users who are not in any of the set's groups
     */
    public List<User> getUsersNotInJoinableSet( List<Group> setGroups )
    {
        // Build a set of all user IDs in any of the set's groups
        Set<String> usersInSet = new HashSet<>();
        for( Group setGroup : setGroups )
        {
            usersInSet.addAll( setGroup.getUsers() );
        }

        // Find users of the site with specified role(s) who are not in any of the set's groups
        List<User> usersNotInSet = new ArrayList<>();
        for( String userID : site.getUsers() )
        {
            if( !usersInSet.contains( userID ) )
            {
                try
                {
                    usersNotInSet.add( userDirectoryService.getUser( userID ) );
                }
                catch( UserNotDefinedException ex )
                {
                    M_log.debug( this + ".getUsersNotInJoinableSet: can't find user for " + userID, ex );
                }
            }
        }

        // Return sorted list of users not in the set
        Collections.sort( usersNotInSet, new UserComparator() );
        return usersNotInSet;
    }

    /**
    * Sorts users by last name, first name, display id
    *
    * @author <a href="mailto:carl.hall@et.gatech.edu">Carl Hall</a>
    */
    private static class UserComparator implements Comparator<User>
    {
        public int compare(User user1, User user2)
        {
            String displayName1 = user1.getLastName() + ", " + user1.getFirstName() + " ("
                    + user1.getDisplayId() + ")";
            String displayName2 = user2.getLastName() + ", " + user2.getFirstName() + " ("
                    + user2.getDisplayId() + ")";
            return displayName1.compareTo( displayName2 );
        }
    }

    /**
     ** Comparator for sorting Group objects
     **/
    private class GroupComparator implements Comparator {
       public int compare(Object o1, Object o2) {
          return ((Group)o1).getTitle().compareToIgnoreCase( ((Group)o2).getTitle() );
       }
    }

    /**
     * Grabs the uploaded file from the groupfile request attribute and extracts the group details
     * from it, adding them to the importedGroups list as it goes. Expects at least three columns,
     * the first three being first name, last name and email respectively.
     * @return status
     */
    public String processUploadAndCheck() {
        String uploadsDone = (String) httpServletRequest.getAttribute(RequestFilter.ATTR_UPLOADS_DONE);

        FileItem usersFileItem;

        if (uploadsDone != null && uploadsDone.equals(RequestFilter.ATTR_UPLOADS_DONE)) {

            try {
                usersFileItem = (FileItem) httpServletRequest.getAttribute(REQ_ATTR_GROUPFILE);

                if(usersFileItem != null && usersFileItem.getSize() > 0) {

                    String mimetype = usersFileItem.getContentType();
                    String filename = usersFileItem.getName();

                    if (ArrayUtils.contains(CSV_MIME_TYPES, mimetype)
                            || StringUtils.endsWith(filename, "csv")) {
                        if (processCsvFile(usersFileItem)) {
                            return "success"; // SHORT CIRCUIT
                        }
                    } else {
                        M_log.error("Invalid file type: " + mimetype);
                        return "error"; // SHORT CIRCUIT
                    }
                }
            }
            catch (Exception e){
                M_log.error(e.getClass() + " : " + e.getMessage());
                return "error"; // SHORT CIRCUIT
            } finally {
                // clear the groupfile attribute so the tool does not have to be reset
                httpServletRequest.removeAttribute(REQ_ATTR_GROUPFILE);
            }
        }

        return "error";
    }

	/**
	 * Helper to process the uploaded CSV file
	 *
	 * @param fileItem
	 * @return
	 */
	private boolean processCsvFile(FileItem fileItem){

		M_log.debug("CSV file uploaded");

		importedGroups = new ArrayList<>();

		CSVReader reader;
		try {
			reader = new CSVReader(new InputStreamReader(fileItem.getInputStream()));
			List<String[]> lines = reader.readAll();

			//maintain a map of the groups and their titles in case the CSV file is unordered
			//this way we can still lookup the group and add members to it
			Map<String, ImportedGroup> groupMap = new HashMap<>();

			for(String[] line: lines){

	            String groupTitle = StringUtils.trim(line[0]);
	            String userId = StringUtils.trim(line[1]);

	            //if we already have an occurrence of this group, get the group and update the user list within it
	            if(groupMap.containsKey(groupTitle)){
	            	ImportedGroup group = groupMap.get(groupTitle);
	            	group.addUser(userId);
	            } else {
	            	ImportedGroup group = new ImportedGroup(groupTitle, userId);
	            	groupMap.put(groupTitle, group);
	            }
			}

			 //extract all of the imported groups from the map
            importedGroups.addAll(groupMap.values());

		} catch (IOException | ArrayIndexOutOfBoundsException ioe) {
			M_log.error(ioe.getClass() + " : " + ioe.getMessage());
			return false;
		}

		return true;
	}

	/**
	 * Helper to check for a valid user in a site, given an eid
	 * @param eid	eid of user,v eg jsmith26
	 * @return
	 */
	public boolean isValidSiteUser(String eid) {
		try {
			User u = userDirectoryService.getUserByEid(eid);
			if(u != null){

				Member m = site.getMember(u.getId());
				if(m != null) {
					return true;
				}
			}
		} catch (UserNotDefinedException e) {
			//not a valid user
			return false;
		}
		return false;
	}

	/**
	 * Helper to get a userId given an eid
	 * @param eid	eid of user,v eg jsmith26
	 * @return
	 */
	public String getUserId(String eid) {
		try {
			return userDirectoryService.getUserId(eid);
		} catch (UserNotDefinedException e) {
			M_log.error("The eid: " + eid + "is invalid.");
			return null;
		}
	}

	/**
	 * Does the actual import of the groups into the site.
	 * @return
	 */
	public String processImportedGroups() {

		//get current groups in this site
		List<Group> existingGroups = getGroups();

		//for each imported group...
		for(ImportedGroup importedGroup: importedGroups) {

			Group group = null;

			//check if the groups already exists
			for(Group g : existingGroups) {
            	if(StringUtils.equals(g.getTitle(), importedGroup.getGroupTitle())) {
            		//use existing group
            		group = g;
            	}
			}

			if(group == null){
        		//create new group
    	        group= site.addGroup();
    	        group.getProperties().addProperty(Group.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString());
    	        group.setTitle(importedGroup.getGroupTitle());
			}

			//add all of the imported members to the group
    		for(String eid: importedGroup.getUserIds()){
    			this.addUserToGroup(eid, group);
    		}

    		try {
    			siteService.save(site);
    			// post event about the participant update
    			EventTrackingService.post(EventTrackingService.newEvent(SiteService.SECURE_UPDATE_GROUP_MEMBERSHIP, group.getId(),true));

    		} catch (IdUnusedException | PermissionException e) {
            	M_log.error("processImportedGroups failed for site: " + site.getId(), e);
            	return "error";
    		}
		}

		return "success";
	}

	/**
	 * Helper to get a list of user eids in a group
	 * @param g	the group
	 * @return
	 */
	public List<String> getGroupUserIds(Group g) {

		List<String> userIds = new ArrayList<>();

		if(g == null) {
			return userIds;
		}

		Set<Member> members= g.getMembers();
		for(Member m: members) {
			userIds.add(m.getUserEid());
		}
		return userIds;
	}

	/**
	 * Helper to add a user to a group. Takes care of the role selection.
	 * @param eid	eid of the user eg jsmith26
	 * @param g		the group
	 */
	private void addUserToGroup(String eid, Group g) {

		//is this a valid site user?
		if(!isValidSiteUser(eid)){
			return;
		}

		//get userId
		String userId = getUserId(eid);
		if(StringUtils.isBlank(userId)) {
			return;
		}

		//is user already in the group?
		if(g.getUserRole(userId) != null) {
			return;
		}

		//add user to group with correct role. This is the same logic as above
		Role r = site.getUserRole(userId);
		Member m = site.getMember(userId);
		Role memberRole = m != null ? m.getRole() : null;
		g.addMember(userId, r != null ? r.getId() : memberRole != null? memberRole.getId() : "", m != null ? m.isActive() : true, false);

	}

	@Setter
	private UserDirectoryService userDirectoryService;

	 /**
     * We need this to get the uploaded file as snaffled by the request filter.
     */
	@Setter
    private HttpServletRequest httpServletRequest;

    /**
     * As we import groups we store the details here for use in further stages
     * of the import sequence.
     */
    @Getter
    private List<ImportedGroup> importedGroups;

    public String processCreateJoinableSet() {
    	// reset the warning messages
    	resetTargettedMessageList();

    	String returnVal = processCreateJoinableSetHelper(true);
    	if(returnVal == null){
    		return null;
    	}else{
    		resetParams();
    		return returnVal;
    	}
    }

    private String processCreateJoinableSetHelper(boolean newSet){
    	joinableSetName = StringUtils.trimToEmpty( joinableSetName );
    	if( StringUtils.isEmpty( joinableSetName ) ){
			messages.addMessage(new TargettedMessage("groupTitle.empty.alert","groupTitle-group"));
			return null;
		}
    	int joinableSetNumOfGroupsInt;
    	joinableSetNumOfGroups = StringUtils.trimToEmpty( joinableSetNumOfGroups );
    	if(joinableSetNumOfGroups == null || "".equals(joinableSetNumOfGroups)){
    		messages.addMessage(new TargettedMessage("numGroups.empty.alert","num-groups"));
			return null;
    	}else{
    		try{
    			joinableSetNumOfGroupsInt = Integer.parseInt(joinableSetNumOfGroups);
    			if(joinableSetNumOfGroupsInt > 1000){
    				messages.addMessage(new TargettedMessage("maxGroups.alert","num-groups"));
        			return null;
    			}
    			if(joinableSetNumOfGroupsInt <= 0){
    				messages.addMessage(new TargettedMessage("numGroups.zero.alert","num-groups"));
    			}
    		}catch (Exception e) {
    			messages.addMessage(new TargettedMessage("numGroups.empty.alert","num-groups"));
    			return null;
			}
    	}
    	int joinableSetNumOfMembersInt;
    	joinableSetNumOfMembers = StringUtils.trimToEmpty( joinableSetNumOfMembers );
    	if(joinableSetNumOfMembers == null || "".equals(joinableSetNumOfMembers)){
    		messages.addMessage(new TargettedMessage("maxMembers.empty.alert","num-groups"));
			return null;
    	}else{
    		try{
    			joinableSetNumOfMembersInt = Integer.parseInt(joinableSetNumOfMembers);
    			if(joinableSetNumOfMembersInt <= 0){
    				messages.addMessage(new TargettedMessage("maxMembers.zero.alert","num-max-members"));
        			return null;
    			}
    		}catch (Exception e) {
    			messages.addMessage(new TargettedMessage("maxMembers.empty.alert","num-max-members"));
    			return null;
			}
    	}

    	Collection siteGroups = site.getGroups();
    	Set<String> groupTitles = new HashSet<>();
		if (siteGroups != null && siteGroups.size() > 0)
		{
			for (Iterator iGroups = siteGroups.iterator(); iGroups.hasNext();) {
				Group iGroup = (Group) iGroups.next();
				groupTitles.add(iGroup.getTitle());
				if(newSet){
					//check that this joinable group name doesn't already exist, if so,
					//warn the user:
					String joinableSetProp = iGroup.getProperties().getProperty(Group.GROUP_PROP_JOINABLE_SET);
					if(joinableSetProp != null && !"".equals(joinableSetProp) && joinableSetProp.equalsIgnoreCase(joinableSetName)){
						//already have a joinable set named this:
						messages.addMessage(new TargettedMessage("joinableset.duplicate.alert","num-max-members"));
		    			return null;
					}
				}
			}
		}
    	for(int i = 1; groupsCreated < joinableSetNumOfGroupsInt && i < 1000; i++){
    		String groupTitle = joinableSetName + " " + i;
    		if(!groupTitles.contains(groupTitle)){
    			Group g = site.addGroup();
    			g.getProperties().addProperty(Group.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString());
    			g.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_SET, joinableSetName);
    			g.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_SET_MAX, joinableSetNumOfMembers);
    			g.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_SET_PREVIEW,Boolean.toString(allowPreviewMembership));
    			g.getProperties().addProperty(Group.GROUP_PROP_VIEW_MEMBERS, Boolean.toString(allowViewMembership));
    			g.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_UNJOINABLE, Boolean.toString(unjoinable));
    			g.setTitle(groupTitle);
    			groupsCreated++;
    			pendingGroupTitles.add( groupTitle );
    		}
    	}

    	if( newSet )
    	{
    		saveSite();
     	}
    	else
    	{
    		resetJoinableSetGroupParams();
    	}

    	return "success";
    }

    /**
     * Utility method to save the site
     */
    private void saveSite()
    {
        try
        {
            siteService.save( site );
        }
        catch( IdUnusedException | PermissionException ex )
        {
            M_log.error( ex );
        }
    }

    public String processDeleteJoinableSet(){
    	// reset the warning messages
    	resetTargettedMessageList();

    	boolean updated = false;
    	for(Group group : site.getGroups()){
    		String joinableSet = group.getProperties().getProperty(Group.GROUP_PROP_JOINABLE_SET);
    		if(joinableSet != null && joinableSet.equals(joinableSetNameOrig)){
    			group.getProperties().removeProperty(Group.GROUP_PROP_JOINABLE_SET);
    			group.getProperties().removeProperty(Group.GROUP_PROP_JOINABLE_SET_MAX);
    			group.getProperties().removeProperty(Group.GROUP_PROP_JOINABLE_SET_PREVIEW);
    			group.getProperties().removeProperty(Group.GROUP_PROP_JOINABLE_UNJOINABLE);
    			updated = true;
    		}
    	}
    	if(updated){
    		saveSite();
    	}

    	resetParams();

    	return "success";
    }

    public String processUpdateJoinableSet(){
    	// reset the warning messages
    	resetTargettedMessageList();

    	String returnVal = processChangeJoinableSetNameHelper( true );
    	if( returnVal != null && returnVal.equals( "success" ) )
    	{
    		resetParams();
    	}

    	return returnVal;
    }

    private String processChangeJoinableSetNameHelper( boolean save ){
    	joinableSetName = StringUtils.trimToEmpty( joinableSetName );
    	if( StringUtils.isEmpty( joinableSetName ) ){
			messages.addMessage(new TargettedMessage("groupTitle.empty.alert","groupTitle-group"));
			return null;
		}
    	if(!joinableSetName.equals(joinableSetNameOrig) || unjoinable != unjoinableOrig){
    		if(!joinableSetName.equals(joinableSetNameOrig)){
    			//check that the new joinable set name doesn't already exist
    			Collection siteGroups = site.getGroups();
    			if (siteGroups != null && siteGroups.size() > 0)
    			{
    				for (Iterator iGroups = siteGroups.iterator(); iGroups.hasNext();) {
    					Group iGroup = (Group) iGroups.next();
    					//check that this joinable group name doesn't already exist, if so,
    					//warn the user:
    					String joinableSetProp = iGroup.getProperties().getProperty(Group.GROUP_PROP_JOINABLE_SET);
    					if(joinableSetProp != null && !"".equals(joinableSetProp) && joinableSetProp.equals(joinableSetName)){
    						//already have a joinable set named this:
    						messages.addMessage(new TargettedMessage("joinableset.duplicate.alert","num-max-members"));
    						return null;
    					}
    				}
    			}
    		}

    		for(Group group : site.getGroups()){
        		String joinableSet = group.getProperties().getProperty(Group.GROUP_PROP_JOINABLE_SET);
        		if(joinableSet != null && joinableSet.equals(joinableSetNameOrig)){
        			group.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_SET, joinableSetName);
        			group.getProperties().addProperty(Group.GROUP_PROP_JOINABLE_UNJOINABLE, Boolean.toString(unjoinable));
        		}
        	}
    	}

    	if( save )
    	{
        	saveSite();
    	}

    	return "success";
    }

    public String processGenerateJoinableSet(){
    	// reset the warning messages
    	resetTargettedMessageList();

    	String returnVal = processChangeJoinableSetNameHelper(false);
    	if(returnVal != null && "success".equals(returnVal))
    	{
        	returnVal = processCreateJoinableSetHelper(false);
        	if(returnVal != null && "success".equals(returnVal))
        	{
        		return null;
        	}
        }

    	return returnVal;
    }
}


text:
@class NSManagedObjectModel;
@class NSManagedObjectContext;
@class NSPersistentStoreCoordinator;

@interface ALCoreDataManager : NSObject

- (instancetype)initWithModelName:(NSString*)modelName;
- (instancetype)initWithInMemoryStore;

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

- (NSManagedObjectContext*)newContext;

- (void)saveAfterPerformingBlock:(void(^)(NSManagedObjectContext *localContext))block
		   withCompletionHandler:(void(^)())completionBlock;

- (void)removeStore;

@end

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace MC\EventBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as  Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * Utilisateur
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="MC\EventBundle\Entity\UtilisateurRepository")
 * @UniqueEntity(fields="adresseMail", message="Cette adresse est déjà utilisée par un utilisateur")
 */
class Utilisateur
{

    /**
    * @ORM\ManyToMany(targetEntity="Evenement", inversedBy="utilisateurs")
    */

    private $evenements;

   /**
   * @ORM\ManyToMany(targetEntity="CA", inversedBy="utilisateurs")
   */

  private $cas;

public function __construct()
{
  $this->evenements = new ArrayCollection();
  $this->cas = new ArrayCollection();
}
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="nomUtilisateur", type="string", length=255)
     * @Assert\Length(min=2, minMessage="Le nom de l'utilisateur doit faire au moins {{ limit }} caractères.")
     */
    private $nomUtilisateur;

    /**
     * @var string
     *
     * @ORM\Column(name="prenomUtilisateur", type="string", length=255)
     * @Assert\Length(min=2, minMessage="Le prénom de l'utilisateur doit faire au moins {{ limit }} caractères.")
     */

    private $prenomUtilisateur;

    /**
     * @var string
     *
     * @ORM\Column(name="adresseMail", type="string", length=255, unique=true)
     * @Assert\Email()
     */
    private $adresseMail;

    /**
     * @var string
     *
     * @ORM\Column(name="motDePasse", type="string", length=255)
     * @Assert\NotBlank()
     */
    private $motDePasse;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set nomUtilisateur
     *
     * @param string $nomUtilisateur
     * @return Utilisateur
     */
    public function setNomUtilisateur($nomUtilisateur)
    {
        $this->nomUtilisateur = $nomUtilisateur;

        return $this;
    }

    /**
     * Get nomUtilisateur
     *
     * @return string
     */
    public function getNomUtilisateur()
    {
        return $this->nomUtilisateur;
    }

    /**
     * Set prenomUtilisateur
     *
     * @param string $prenomUtilisateur
     * @return Utilisateur
     */
    public function setPrenomUtilisateur($prenomUtilisateur)
    {
        $this->prenomUtilisateur = $prenomUtilisateur;

        return $this;
    }

    /**
     * Get prenomUtilisateur
     *
     * @return string
     */
    public function getPrenomUtilisateur()
    {
        return $this->prenomUtilisateur;
    }

    /**
     * Set adresseMail
     *
     * @param string $adresseMail
     * @return Utilisateur
     */
    public function setAdresseMail($adresseMail)
    {
        $this->adresseMail = $adresseMail;

        return $this;
    }

    /**
     * Get adresseMail
     *
     * @return string
     */
    public function getAdresseMail()
    {
        return $this->adresseMail;
    }

    /**
     * Set motDePasse
     *
     * @param string $motDePasse
     * @return Utilisateur
     */
    public function setMotDePasse($motDePasse)
    {
        $this->motDePasse = $motDePasse;

        return $this;
    }

    /**
     * Get motDePasse
     *
     * @return string
     */
    public function getMotDePasse()
    {
        return $this->motDePasse;
    }

    /**
     * Add evenements
     *
     * @param \MC\EventBundle\Entity\Evenement $evenements
     * @return Utilisateur
     */
    public function addEvenement(\MC\EventBundle\Entity\Evenement $evenements)
    {
        $this->evenements[] = $evenements;

        return $this;
    }

    /**
     * Remove evenements
     *
     * @param \MC\EventBundle\Entity\Evenement $evenements
     */
    public function removeEvenement(\MC\EventBundle\Entity\Evenement $evenements)
    {
        $this->evenements->removeElement($evenements);
    }

    /**
     * Get evenements
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getEvenements()
    {
        return $this->evenements;
    }

    /**
     * Add cas
     *
     * @param \MC\EventBundle\Entity\CA $cas
     * @return Utilisateur
     */
    public function addCa(\MC\EventBundle\Entity\CA $cas)
    {
        $this->cas[] = $cas;

        return $this;
    }

    /**
     * Remove cas
     *
     * @param \MC\EventBundle\Entity\CA $cas
     */
    public function removeCa(\MC\EventBundle\Entity\CA $cas)
    {
        $this->cas->removeElement($cas);
    }

    /**
     * Get cas
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getCas()
    {
        return $this->cas;
    }
}


text:
/*!
 *  Copyright (c) 2018 by Contributors.
 *
 * \file tvm/relay/pass/quantize.h
 * \brief Header of definitions for quantization
 */
#ifndef TVM_RELAY_PASS_QUANTIZE_QUANTIZE_H_
#define TVM_RELAY_PASS_QUANTIZE_QUANTIZE_H_

#include <tvm/relay/op.h>
#include <tvm/relay/expr.h>
#include <string>
#include "../pattern_util.h"

namespace tvm {
namespace relay {
namespace quantize {

/*! \brief Kind of annotate field */
enum QAnnotateKind : int {
  kQIdentity = 0,
  kQInput = 1,
  kQWeight = 2,
  kQActivation = 3
};

/*! \brief Attribute for simulated quantize operator */
struct SimulatedQuantizeAttrs : public tvm::AttrsNode<SimulatedQuantizeAttrs> {
  int kind;
  bool sign;
  std::string rounding;

  TVM_DECLARE_ATTRS(SimulatedQuantizeAttrs, "relay.attrs.SimulatedQuantizeAttrs") {
    TVM_ATTR_FIELD(kind)
        .describe("kind of field, hint for nbit/dtype configuration.");
    TVM_ATTR_FIELD(sign).set_default(true)
        .describe("whether to use signed data type.");
    TVM_ATTR_FIELD(rounding).set_default("round")
        .describe("rounding mode. Can be 'floor', 'ceil', 'round'");
  }
};

class QConfig;
/*!
* \brief Container for build configuration options
*/
class QConfigNode : public Node {
 public:
  int nbit_input = 8;
  int nbit_weight = 8;
  int nbit_activation = 32;
  DataType dtype_input = Int(8);
  DataType dtype_weight = Int(8);
  DataType dtype_activation = Int(32);
  double global_scale = 8.0;
  Array<Expr> skip_conv_layers = Array<Expr>(NodePtr<Node>(nullptr));
  bool do_simulation = false;
  bool round_for_shift = true;
  Array<Expr> debug_enabled_ops = Array<Expr>(NodePtr<Node>(nullptr));

  void VisitAttrs(AttrVisitor* v) final {
    v->Visit("nbit_input", &nbit_input);
    v->Visit("nbit_weight", &nbit_weight);
    v->Visit("nbit_activation", &nbit_activation);
    v->Visit("dtype_input", &dtype_input);
    v->Visit("dtype_weight", &dtype_weight);
    v->Visit("dtype_activation", &dtype_activation);
    v->Visit("global_scale", &global_scale);
    v->Visit("skip_conv_layers", &skip_conv_layers);
    v->Visit("do_simulation", &do_simulation);
    v->Visit("round_for_shift", &round_for_shift);
    v->Visit("debug_enabled_ops", &debug_enabled_ops);
  }

  static constexpr const char* _type_key = "relay.quantize.QConfig";
  TVM_DECLARE_NODE_TYPE_INFO(QConfigNode, Node);
};

/*!
* \brief Container for build configuration options
*/
class QConfig : public NodeRef {
 public:
  QConfig() {}
  explicit QConfig(NodePtr<Node> n) : NodeRef(n) {}

  const QConfigNode* operator->() const {
    return static_cast<const QConfigNode*>(node_.get());
  }

  QConfigNode* operator->() {
    return static_cast<QConfigNode*>(node_.get());
  }

  /*!
   * \brief Push a new BuildConfig context onto the thread local stack.
   * \param build_config The configuration to set as the current context.
   */
  static void EnterQConfigScope(const QConfig& qconfig);

  /*!
   * \brief Pop a build config off the thread local context stack, restoring the previous
   * configuration as the current context.
   */
  static void ExitQConfigScope();

  /*!
   * \brief Get the current BuildConfig context from thread local storage, or a default
   * configuration if a BuildConfig scope has not been entered.
   * \return The configuration that is the current context.
   */
  static QConfig& Current();

  using ContainerType = QConfigNode;
};

/*!
 * \brief RAII container to provide a scoped BuildConfig context. Pushes a configuration onto the
 * context stack when constructed, and pops it when destructed.
 */
struct QConfigContext {
  /*!
   * \brief Enter a new BuildConfig context. The given BuildConfig becomes the new current
   * context. When the BuildConfigContext is destructed, the previous context is restored.
   * \param build_config The BuildConfig to set as the new current context.
   */
  explicit QConfigContext(const QConfig& qconfig) {
    QConfig::EnterQConfigScope(qconfig);
  }

  /*! \brief Destructor. Pops the context off the thread local stack. */
  ~QConfigContext() {
    QConfig::ExitQConfigScope();
  }
};

}  // namespace quantize
}  // namespace relay
}  // namespace tvm
#endif  // TVM_RELAY_PASS_QUANTIZE_QUANTIZE_H_


text:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content_shopping_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#faf7f7"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="7dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_empty_cart"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="?android:attr/listPreferredItemHeight"
            android:layout_marginBottom="?android:attr/listPreferredItemHeight"
            android:gravity="center"
            android:textSize="20sp"
            android:visibility="gone"
            android:textColor="#000000"
            android:text="You have no items in the cart"/>

        <ImageView
            android:id="@+id/iv_empty_cart"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:visibility="gone"
            android:layout_marginBottom="?android:attr/listPreferredItemHeight"
            android:layout_gravity="center"
            android:background="@drawable/ic_add_shopping_cart_black_24dp"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/card_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <TextView
            android:id="@+id/txt_price"
            android:layout_marginTop="20dp"
            android:layout_marginBottom="5dp"
            android:layout_gravity="center"
            android:textColor="@color/colorAccent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <Button
            android:id="@+id/btn_buy"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:text="@string/label_check_out"
            android:layout_marginTop="10dp"
            android:layout_gravity="center"
            android:textColor="@android:color/white"
            android:background="@drawable/rounded_buy"/>

    </LinearLayout>
</android.support.v4.widget.NestedScrollView>


text:
<component name="ProjectRunConfigurationManager">
  <configuration default="false" name="Debug Buck Test" type="Remote" factoryName="Remote" singleton="true">
    <option name="USE_SOCKET_TRANSPORT" value="true" />
    <option name="SERVER_MODE" value="false" />
    <option name="SHMEM_ADDRESS" value="javadebug" />
    <option name="HOST" value="localhost" />
    <option name="PORT" value="5005" />
    <RunnerSettings RunnerId="Debug">
      <option name="DEBUG_PORT" value="5005" />
      <option name="LOCAL" value="false" />
    </RunnerSettings>
    <method />
  </configuration>
</component>


text:
function logout (req, res) {
	var user = req.user;
	var snowpi = this;
	var keystone = snowpi.keystone;

	keystone.callHook(user, 'pre:signout', function (err) {
		if (err) {
			return res.snowpiResponse({action:'greeter',command:'logout',success:'no',message:'Error logging out',code:401,data:{}});
		}
		res.clearCookie('keystone.uid');
		req.user = null;
		req.session.regenerate(function (err) {
			if (err) return res.json({ error: 'session error', detail: err });
			keystone.callHook(user, 'post:signout', function (err) {
				if (err) {
					return res.snowpiResponse({action:'greeter',command:'logout',success:'no',message:'Error logging out.',code:401,data:{}});
				}
				res.redirect(keystone.get('signout redirect') || keystone.get('signin url'));
			});
		});
	});
}

module.exports = logout;


text:
import React from 'react'
import {browserHistory,Link} from 'react-router'

import Navigation from '../navigation/navigation.js'
import MovieList from '../movielist/movielist.js'

require('./home.scss');

const axios = require('axios')

class Home extends React.Component{
    constructor(){
        console.log('home')
        super();
        window.location.replace('http://'+window.location.host+'/#/category/now_playing')
    }

    render() {
      return (
        <div>

        </div>
      )
    }
}

export {Home as default}


text:
var testRoundNumber = 0;

// The test pattern cycles as a color fill of red, then green, then blue.
var colors = [ [ 255, 0, 0 ], [ 0, 255, 0 ], [ 0, 0, 255 ] ];
var curIdx = 0;

// Capture parameters.
var width = 64;
var height = 48;
var frameRate = 15;

// The stream to playback in the video element.
var receiveStream = null;

// waitForExpectedColors() removes elements from this array as each is observed.
// When it becomes empty, the test succeeds.
var expectedColors = [ [ 255, 0, 0 ], [ 0, 255, 0 ], [ 0, 0, 255 ] ];

function updateTestPattern() {
  if (!this.canvas) {
    this.canvas = document.createElement("canvas");
    this.canvas.width = 320;
    this.canvas.height = 200;
    this.canvas.style.position = "absolute";
    this.canvas.style.top = "0px";
    this.canvas.style.left = "0px";
    this.canvas.style.width = "100%";
    this.canvas.style.height = "100%";
    document.body.appendChild(this.canvas);
  }
  var context = this.canvas.getContext("2d");
  // Fill with solid color.
  context.fillStyle = "rgb(" + colors[curIdx] + ")";
  context.fillRect(0, 0, this.canvas.width, this.canvas.height);
  // Draw the circle that moves around the page.
  context.fillStyle = "rgb(" + colors[(curIdx + 1) % colors.length] + ")";
  context.beginPath();
  if (!this.frameNumber) {
    this.frameNumber = 1;
  } else {
    ++this.frameNumber;
  }
  var i = this.frameNumber % 200;
  var t = (this.frameNumber + 3000) * (0.01 + i / 8000.0);
  var x = (Math.sin(t) * 0.45 + 0.5) * this.canvas.width;
  var y = (Math.cos(t * 0.9) * 0.45 + 0.5) * this.canvas.height;
  context.arc(x, y, 16, 0, 2 * Math.PI, false);
  context.closePath();
  context.fill();
}

function renderTestPatternLoop() {
  requestAnimationFrame(renderTestPatternLoop);
  updateTestPattern();

  if (!this.stepTimeMillis) {
    this.stepTimeMillis = 100;
  }
  var now = new Date().getTime();
  if (!this.nextSteppingAt) {
    this.nextSteppingAt = now + this.stepTimeMillis;
  } else if (now >= this.nextSteppingAt) {
    ++curIdx;
    if (curIdx >= colors.length) {  // Completed a cycle.
      curIdx = 0;
      // Increase the wait time between switching test patterns for overloaded
      // bots that aren't capturing all the frames of video. Only do this for
      // the first test phase, since increases shouldn't be needed after that.
      if (testRoundNumber == 0) {
        this.stepTimeMillis *= 1.25;
      }
    }
    this.nextSteppingAt = now + this.stepTimeMillis;
  }
}

function waitForExpectedColors(colorDeviation) {
  // At the start of a round of testing, create the video and canvas elements,
  // but no need to append them to the DOM.
  if (!this.video) {
    this.video = document.createElement("video");
    this.video.width = width;
    this.video.height = height;
    this.video.addEventListener("error", chrome.test.fail);
    this.video.srcObject = receiveStream;
    this.video.play();

    this.readbackCanvas = document.createElement("canvas");
    this.readbackCanvas.width = width;
    this.readbackCanvas.height = height;
  }

  // Only bother examining a video frame if the video timestamp has advanced.
  var currentVideoTimestamp = this.video.currentTime;
  if (!this.lastVideoTimestamp ||
      this.lastVideoTimestamp < currentVideoTimestamp) {
    this.lastVideoTimestamp = currentVideoTimestamp;

    // Grab a snapshot of the center pixel of the video.
    var ctx = this.readbackCanvas.getContext("2d");
    ctx.drawImage(video, 0, 0, width, height);
    var imageData = ctx.getImageData(width / 2, height / 2, 1, 1);
    var pixel = [ imageData.data[0], imageData.data[1], imageData.data[2] ];

    // Does the pixel match one of the expected colors?
    for (var i = 0; i < expectedColors.length; ++i) {
      var curColor = expectedColors[i];
      if (Math.abs(pixel[0] - curColor[0]) <= colorDeviation &&
          Math.abs(pixel[1] - curColor[1]) <= colorDeviation &&
          Math.abs(pixel[2] - curColor[2]) <= colorDeviation) {
        console.debug(`${testRoundNumber == 0 ? 'First' : 'Second'} round: ` +
            `Observed expected color RGB(${curColor}) in the video as ` +
            `RGB(${pixel})`);
        expectedColors.splice(i, 1);
      }
    }
  }

  if (expectedColors.length == 0) {
    // Successful end of the current test round. If the first round, sleep, then
    // execute the second round. If the second round, then the whole test has
    // succeeded.
    if (testRoundNumber == 0) {
      // Destroy the video, which will disconnect the consumer of the
      // MediaStream.
      this.video.removeEventListener("error", chrome.test.fail);
      this.video.srcObject = null;
      this.video = null;

      // Wait one second, then execute the second round of testing. This tests
      // the suspend/resume functionality of tab capture (w.r.t. a MediaStream
      // having no consumers, and then being re-used with a new consumer).
      console.debug('First round succeeded! Now testing suspend/resume...');
      setTimeout(function() {
        ++testRoundNumber;
        for (const color of colors) {
          expectedColors.push(color);
        }
        waitForExpectedColors(colorDeviation);
      }, 1000);
    } else {
      chrome.test.succeed();
    }
  } else {
    setTimeout(function () { waitForExpectedColors(colorDeviation); },
               1000 / frameRate);
  }
}

chrome.test.runTests([
  function endToEndTest() {
    // The receive port changes between browser_test invocations, and is passed
    // as an query parameter in the URL.
    var transportMethod;  // Should be: local or webrtc.
    var colorDeviation;  // How far from the expected intensity ([0,255] scale)?
    try {
      transportMethod = window.location.search.match(/(\?|&)method=(\w+)/)[2];
      chrome.test.assertTrue(transportMethod == 'local' ||
                             transportMethod == 'webrtc');
      colorDeviation = parseInt(
          window.location.search.match(/(\?|&)colorDeviation=(\d+)/)[2]);
      chrome.test.assertTrue(colorDeviation >= 0 && colorDeviation <= 255);
    } catch (err) {
      chrome.test.fail("Error parsing query params -- " + err.message);
      return;
    }

    // Start rendering test patterns.
    renderTestPatternLoop();

    chrome.tabCapture.capture(
        { video: true,
          audio: true,
          videoConstraints: {
            mandatory: {
              minWidth: width,
              minHeight: height,
              maxWidth: width,
              maxHeight: height,
              maxFrameRate: frameRate,
            }
          }
        },
        function remoteTheStream(captureStream) {
          chrome.test.assertTrue(!!captureStream);
          if (transportMethod == 'local') {
            receiveStream = captureStream;
            waitForExpectedColors(colorDeviation);
          } else if (transportMethod == 'webrtc') {
            var sender = new RTCPeerConnection();
            var receiver = new RTCPeerConnection();
            sender.onicecandidate = function (event) {
              if (event.candidate) {
                receiver.addIceCandidate(new RTCIceCandidate(event.candidate));
              }
            };
            receiver.onicecandidate = function (event) {
              if (event.candidate) {
                sender.addIceCandidate(new RTCIceCandidate(event.candidate));
              }
            };
            receiver.onaddstream = function (event) {
              receiveStream = event.stream;
              waitForExpectedColors(colorDeviation);
            };
            sender.addStream(captureStream);
            sender.createOffer(function (sender_description) {
              sender.setLocalDescription(sender_description);
              receiver.setRemoteDescription(sender_description);
              receiver.createAnswer(function (receiver_description) {
                receiver.setLocalDescription(receiver_description);
                sender.setRemoteDescription(receiver_description);
              }, function (error) {
              });
            }, function (error) {
            });
          } else {
            chrome.test.fail("Unknown transport method: " + transportMethod);
          }
        });
  }
]);

// TODO(miu): Once the WebAudio API is finalized, we should add a test to emit a
// tone from the sender page, and have the receiver page check for the audio
// tone.


text:
var traverse = require("../lib/6to5/traverse");
var assert   = require("assert");
var _        = require("lodash");

suite("traverse", function () {
  var ast = {
    type: "Program",
    body: [
      {
        "type": "VariableDeclaration",
        "declarations": [
          {
            "type": "VariableDeclarator",
            "id": {
              "type": "Identifier",
              "name": "foo",
            },
            "init": {
              "type": "Literal",
              "value": "bar",
              "raw": "\'bar\'"
            }
          }
        ],
        "kind": "var"
      },
      {
        "type": "ExpressionStatement",
        "expression": {
          "type": "AssignmentExpression",
          "operator": "=",
          "left": {
            "type": "MemberExpression",
            "computed": false,
            "object": {
              "type": "ThisExpression"
            },
            "property": {
              "type": "Identifier",
              "name": "test"
            }
          },
          "right": {
            "type": "Literal",
            "value": "wow",
            "raw": "\'wow\'"
          }
        }
      }
    ]
  };

  var body = ast.body;

  test("hasType", function () {
    assert.ok(traverse.hasType(ast, "ThisExpression"));
    assert.ok(!traverse.hasType(ast, "ThisExpression", ["AssignmentExpression"]));
  });

  test("traverse", function () {
    var expect = [
      body[0], body[0].declarations[0], body[0].declarations[0].id, body[0].declarations[0].init,
      body[1], body[1].expression, body[1].expression.left, body[1].expression.left.object, body[1].expression.left.property, body[1].expression.right
    ];

    var actual = [];

    traverse(ast, {
      enter: function (node) {
        actual.push(node);
      }
    });

    assert.deepEqual(actual, expect);
  });

  test("traverse falsy parent", function () {
    traverse(null, {
      enter: function () {
        throw new Error("should not be ran");
      }
    });
  });

  test("traverse unknown type", function () {
    traverse({
      type: "FooBar"
    }, {
      enter: function () {
        throw new Error("should not be ran");
      }
    });
  });

  test("traverse blacklistTypes", function () {
    var expect = [
      body[0], body[0].declarations[0], body[0].declarations[0].id, body[0].declarations[0].init,
      body[1], body[1].expression, body[1].expression.right
    ];

    var actual = [];

    traverse(ast, {
      blacklist: ["MemberExpression"],
      enter: function (node) {
        actual.push(node);
      }
    });

    assert.deepEqual(actual, expect);
  });

  test("traverse replace", function () {
    var replacement = {
      type: "Literal",
      value: "foo"
    };
    var ast2 = _.cloneDeep(ast);

    traverse(ast2, {
      enter: function (node) {
        if (node.type === "ThisExpression") return replacement;
      }
    });

    assert.equal(ast2.body[1].expression.left.object, replacement);
  });

  test("hasType", function () {
    assert.ok(traverse.hasType(ast, "ThisExpression"));
    assert.ok(traverse.hasType(ast, "Program"));

    assert.ok(!traverse.hasType(ast, "ThisExpression", ["MemberExpression"]));
    assert.ok(!traverse.hasType(ast, "ThisExpression", ["Program"]));

    assert.ok(!traverse.hasType(ast, "ArrowFunctionExpression"));
  });
});


text:
package example;

public class Calculations {

	int x = 5;

	public int calculateSomethings(int y, int z) {
		return x * y * z;
	}

	public int someOtherCalculations(int y, int z) {
		return x  / y / z;
	}
}


text:
#!/usr/bin/env node
'use strict';

/**
 * Run singpath-core unit tests.
 */

const sh = require('shelljs');
const tools = require('@singpath/tools');
const src = 'singpath-core/singpath-core.specs.js';

// exit on error
sh.set('-e');

tools.mocha(src, {
  config(loader) {
    loader.config({
      map: {
        css: loader.map.text,
        'ace/mode-html.js': '@empty',
        'ace/mode-java.js': '@empty',
        'ace/mode-javascript.js': '@empty',
        'ace/mode-python.js': '@empty',
        'ace/theme-twilight.js': '@empty',
        ace: '@empty'
      }
    });
  }
});


text:
module ActiveSupport
  class TimeWithZone
    def seconds_since
      (Time.now - self).to_i
    end

    def minutes_since
      seconds_since/60
    end

    def hours_since
      minutes_since/60
    end
  end
end


text:
title: Blog Three
layout: post
author: amal.shakir
permalink: /blog-three/
source-id: 1QMeNXMM-bIPRF-bYf-5-ynVh8nvltJl7JjxSZgsEneY
published: true
---
**Blog Three**

A lesson on discrimination and other social issues, not your everyday I.T lesson. We started the lesson by doing a survey on discrimination and how we treat each other in school.

Sir lectured us on how the use of the 'N' word and the word rape and gay are unforgivably horrible to use.

I found that I would be going to Oxford for a treasure hunt for my enrichment day,

We finished the day by doing some more work on our game plans.

I'll write back soon!


text:
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

class DeletePrefixTest
{
    static void Main()
    {
        Console.WriteLine(@"Delete from a text file all words that start with the prefix 'test'\n");

        Console.WriteLine(@"The text file is named '..\..\Readme.txt'");
        Console.WriteLine(@"(The resulting file is saved in '..\..\ReadmeResult.txt'");
        Console.WriteLine("\nPlease, open these files to see the result.");

        StreamReader reader = new StreamReader("../../Readme.txt");
        StreamWriter writer = new StreamWriter("../../ReadmeResult.txt");
        string line = "";

        using (reader)
        {
            using (writer)
            {
                line = reader.ReadLine();
                while (line != null)
                {
                    line = line.ToLower();
                    line = Regex.Replace(line, @"\btest\w*(\s|\S)\b", "");
                    writer.WriteLine(line);
                    line = reader.ReadLine();
                }
            }
        }
    }
}


text:
using AutoMapper;
using Sisacon.Application;
using Sisacon.Application.Interfaces;
using Sisacon.Domain.Entities;
using Sisacon.UI.ViewModels;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;

namespace Sisacon.UI.Controllers
{
    [RoutePrefix("api")]
    public class CompanyController : BaseController
    {
        private readonly ICompanyAppService _companyAppService;

        public CompanyController(ICompanyAppService companyAppService)
        {
            _companyAppService = companyAppService;
        }

        [HttpPost]
        [Route("company")]
        public HttpResponseMessage Save(CompanyViewModel companyViewModel)
        {
            var response = new ResponseMessage<Company>();

            try
            {
                if (ModelState.IsValid)
                {
                    var company = Mapper.Map<CompanyViewModel, Company>(companyViewModel);

                    response = _companyAppService.saveOrUpdate(company);
                }
                else
                {
                    response = response.createInvalidResponse();
                }
            }
            catch
            {
                response = response.createErrorResponse();
            }

            return Request.CreateResponse(response.StatusCode, response);
        }

        [HttpPost]
        [Route("company/{idUser:int}")]
        public HttpResponseMessage AddLogo(int idUser)
        {
            var response = new ResponseMessage<Company>();

            var company = _companyAppService.getCompanyByUserId(idUser);

            if (company.Value != null)
            {
                var httpRequest = HttpContext.Current.Request;

                if (httpRequest.Files.Count > 0)
                {
                    var stream = httpRequest.Files[0].InputStream;
                    var length = httpRequest.Files[0].ContentLength;

                    company.Value.Logo = ConvertHttpContextToByte(stream, length);

                    response = _companyAppService.saveOrUpdate(company.Value);
                }
                else
                {
                    return Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
                }
            }
            else
            {
                response = response.createErrorResponse();
            }

            return Request.CreateResponse(response.StatusCode, response);
        }

        [HttpGet]
        [Route("company")]
        public HttpResponseMessage GetCompanyByUser(int id)
        {
            var response = _companyAppService.getCompanyByUserId(id);

            return Request.CreateResponse(response.StatusCode, response);
        }

        [HttpGet]
        [Route("company")]
        public HttpResponseMessage GetOccupationArea()
        {
            var response = _companyAppService.getOccupationAreas();

            return Request.CreateResponse(response.StatusCode, response);
        }
    }
}


text:
package com.jeffpdavidson.fantasywear.protocol;

/**
 * Constants defining path prefixes for communication to/from the wear device.
 *
 * Must be kept in sync with the IntentFilters for the mobile and wear WearableListenerService
 * implementations.
 */
public final class Paths {
    private Paths() {}

    /** Path for league data. Use {@link LeagueData} rather than using this directly. */
    static final String LEAGUE = "league";

    /** Path used with the MessageApi for the wear device to request a sync on the host device. */
    public static final String SYNC = "sync";

    /**
     * Path used with the MessageApi for the wear device to acknowledge a sync.
     *
     * Used to work around an apparent Wear bug where the first few DataItems don't immediately
     * reach the Wear device. For the initial sync of a league, we send messages every few seconds
     * until we receive an ACK from the wear device.
     */
    public static final String ACK = "ack";
}