/*==========================================================================*\
| $Id: FilteringUserSelector.java,v 1.3 2012/03/28 13:48:08 stedwar2 Exp $
|*-------------------------------------------------------------------------*|
| Copyright (C) 2010-2012 Virginia Tech
|
| This file is part of Web-CAT.
|
| Web-CAT is free software; you can redistribute it and/or modify
| it under the terms of the GNU Affero General Public License as published
| by the Free Software Foundation; either version 3 of the License, or
| (at your option) any later version.
|
| Web-CAT is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU Affero General Public License
| along with Web-CAT; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/
package org.webcat.core;
import java.util.Arrays;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.webcat.ui.generators.JavascriptGenerator;
import org.webcat.ui.util.ComponentIDGenerator;
import com.webobjects.appserver.WOActionResults;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WOResponse;
import com.webobjects.eocontrol.EOFetchSpecification;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSMutableArray;
import er.extensions.eof.ERXFetchSpecificationBatchIterator;
import er.extensions.eof.ERXQ;
import er.extensions.eof.ERXSortOrdering.ERXSortOrderings;
import er.extensions.foundation.ERXArrayUtilities;
//-------------------------------------------------------------------------
/**
* A reusable component that allows a user to select a set of users, for things
* like course enrollment or assigning partners to a submission.
*
* @binding simpleLayout if true, the user list will be a simple list of names
* separated by BR tags, with the edit button underneath, suitable for
* embedding in a small page element such as a table cell. If false (the
* default), a fuller UI will be displayed
* @binding actionTitle the string displayed in the edit button and in the
* title of the dialog
* @binding dialogMessage a message displayed in the dialog box
* @binding hidesTableOnEmptySelection if true, the master list of users will
* be hidden if there are no users selected; if false, the list will be
* shown as a table that reads "No users are currently selected." Defaults
* to false.
* @binding selectedListTitle the string to display for the title of the
* list of selected users; if omitted, "Selected Users" will be used
* @binding availableListTitle the string to display for the title of the list
* of available users; if omitted, "Available Users" will be used
* @binding qualifier a qualifier used to filter the master list of available
* users
* @binding selectedUsers the array of users who are selected in the list
*
* @author Tony Allevato
* @author Last changed by $Author: stedwar2 $
* @version $Revision: 1.3 $, $Date: 2012/03/28 13:48:08 $
*/
public class FilteringUserSelector
extends WCComponent
{
//~ Constructors ..........................................................
// ----------------------------------------------------------
public FilteringUserSelector(WOContext context)
{
super(context);
}
//~ KVC attributes (must be public) .......................................
// Public bindings
public boolean simpleLayout;
public String actionTitle;
public String dialogMessage;
public String selectedListTitle;
public String availableListTitle;
public boolean hidesTableOnEmptySelection;
// Used internally
public ComponentIDGenerator idFor;
public NSMutableArray<User> editingUsers;
public User aSelectedUser;
public User anAvailableUser;
public int index;
//~ Methods ...............................................................
// ----------------------------------------------------------
@Override
public void appendToResponse(WOResponse response, WOContext context)
{
idFor = new ComponentIDGenerator(this);
if (selectedUsers == null)
{
selectedUsers = new NSMutableArray<User>();
}
if (editingUsers == null)
{
editingUsers = selectedUsers.mutableClone();
}
if (availableUsers == null)
{
resetAvailableUsers();
}
super.appendToResponse(response, context);
}
// ----------------------------------------------------------
private void resetAvailableUsers()
{
EOFetchSpecification fspec = new EOFetchSpecification(
User.ENTITY_NAME, fullQualifier(), USER_SORT_CRITERIA);
batchIterator = new ERXFetchSpecificationBatchIterator(
fspec, localContext(), BATCH_SIZE);
availableUsers = new NSMutableArray<User>();
addNextBatchToAvailableUsers();
}
// ----------------------------------------------------------
private void addNextBatchToAvailableUsers()
{
if (batchIterator.hasNextBatch())
{
@SuppressWarnings("unchecked")
NSArray<User> batch = batchIterator.nextBatch();
availableUsers.addObjectsFromArray(batch);
}
}
// ----------------------------------------------------------
public boolean isEmptySelectionAndHide()
{
return hidesTableOnEmptySelection && selectedUsers.count() == 0;
}
// ----------------------------------------------------------
/**
* Gets the full JavaScript reference to the proxy object that is used to
* make RPC calls to the server-side component.
*
* @return the full JavaScript reference to the proxy object
*/
public String proxyReference()
{
return idFor.valueForKey("jsonrpc") + ".userSelector";
}
// ----------------------------------------------------------
public String actionTitle()
{
if (actionTitle == null)
{
return DEFAULT_ACTION_TITLE;
}
else
{
return actionTitle;
}
}
// ----------------------------------------------------------
public String selectedListTitle()
{
if (selectedListTitle == null)
{
return DEFAULT_SELECTED_LIST_TITLE;
}
else
{
return selectedListTitle;
}
}
// ----------------------------------------------------------
public String availableListTitle()
{
if (availableListTitle == null)
{
return DEFAULT_AVAILABLE_LIST_TITLE;
}
else
{
return availableListTitle;
}
}
// ----------------------------------------------------------
public NSArray<User> selectedUsers()
{
return selectedUsers;
}
// ----------------------------------------------------------
public void setSelectedUsers(NSArray<User> someUsers)
{
@SuppressWarnings("unchecked")
NSMutableArray<User> result =
new NSMutableArray<User>(
ERXArrayUtilities.arrayWithoutDuplicates(someUsers));
selectedUsers = result;
}
// ----------------------------------------------------------
public EOQualifier qualifier()
{
return qualifier;
}
// ----------------------------------------------------------
public void setQualifier(EOQualifier aQualifier)
{
qualifier = aQualifier;
}
// ----------------------------------------------------------
public EOQualifier fullQualifier()
{
EOQualifier filter = nameFilteringQualifier();
if (qualifier != null && filter != null)
{
return ERXQ.and(qualifier, filter);
}
else if (filter != null)
{
return filter;
}
else
{
return qualifier;
}
}
// ----------------------------------------------------------
private EOQualifier nameFilteringQualifier()
{
EOQualifier filter = null;
if (filterString != null)
{
String likeString = "*" + filterString + "*";
filter = ERXQ.or(
User.userName.likeInsensitive(likeString),
User.firstName.likeInsensitive(likeString),
User.lastName.likeInsensitive(likeString));
}
return filter;
}
// ----------------------------------------------------------
public NSArray<User> availableUsers()
{
return availableUsers;
}
// ----------------------------------------------------------
public boolean areMoreUsersAvailable()
{
if (batchIterator != null)
{
return batchIterator.hasNextBatch();
}
else
{
return false;
}
}
// ----------------------------------------------------------
public WOActionResults okPressed()
{
selectedUsers = editingUsers.mutableClone();
// pushValuesToParent();
JavascriptGenerator script = new JavascriptGenerator();
script.refresh(idFor.get("masterPane")).
dijit(idFor.get("dialog")).call("hide");
return script;
}
// ----------------------------------------------------------
public void updateFilter(String aFilterString)
{
filterString = aFilterString;
resetAvailableUsers();
}
// ----------------------------------------------------------
public void addToSelectedUsers(JSONArray availableIndices)
{
for (int i = 0; i < availableIndices.length(); i++)
{
try
{
int availableIndex = availableIndices.getInt(i);
User user = availableUsers.objectAtIndex(availableIndex);
if (!editingUsers.containsObject(user))
{
editingUsers.addObject(user);
}
}
catch (JSONException e)
{
log.warn(e);
}
}
USER_SORT_CRITERIA.sort(editingUsers);
}
// ----------------------------------------------------------
public void deleteFromSelectedUsers(JSONArray selectedIndices)
{
int[] indices = new int[selectedIndices.length()];
for (int i = 0; i < selectedIndices.length(); i++)
{
try
{
indices[i] = selectedIndices.getInt(i);
}
catch (JSONException e)
{
log.warn(e);
}
}
Arrays.sort(indices);
int displacement = 0;
for (int i = 0; i < indices.length; i++)
{
editingUsers.removeObjectAtIndex(indices[i] - displacement);
displacement++;
}
}
// ----------------------------------------------------------
public JavascriptGenerator showMoreUsers()
{
addNextBatchToAvailableUsers();
return new JavascriptGenerator().refresh(
idFor.get("availableUsersPane"));
}
// ----------------------------------------------------------
public String openDialogScript()
{
return "dijit.byId('" + idFor.get("dialog") + "').show();";
}
//~ Static/instance variables .............................................
private static final int BATCH_SIZE = 12;
private static final String DEFAULT_ACTION_TITLE =
"Edit Selected Users...";
private static final String DEFAULT_SELECTED_LIST_TITLE =
"Selected users";
private static final String DEFAULT_AVAILABLE_LIST_TITLE =
"Available users";
private static final ERXSortOrderings USER_SORT_CRITERIA =
User.lastName.ascInsensitive().then(
User.userName.ascInsensitive());
private ERXFetchSpecificationBatchIterator batchIterator;
private NSMutableArray<User> selectedUsers;
private EOQualifier qualifier;
private String filterString;
private NSMutableArray<User> availableUsers;
private static final Logger log = Logger.getLogger(
FilteringUserSelector.class);
}