001: /*
002: * FlowGroupUtils.java
003: *
004: * Version: $Revision: 1.3 $
005: *
006: * Date: $Date: 2006/07/13 23:20:54 $
007: *
008: * Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
009: * Institute of Technology. All rights reserved.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions are
013: * met:
014: *
015: * - Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * - Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in the
020: * documentation and/or other materials provided with the distribution.
021: *
022: * - Neither the name of the Hewlett-Packard Company nor the name of the
023: * Massachusetts Institute of Technology nor the names of their
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
030: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
032: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
033: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
034: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
036: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
037: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
038: * DAMAGE.
039: */package org.dspace.app.xmlui.aspect.administrative;
040:
041: import java.io.UnsupportedEncodingException;
042: import java.net.URLDecoder;
043: import java.sql.SQLException;
044: import java.util.ArrayList;
045: import java.util.Arrays;
046: import java.util.List;
047:
048: import org.dspace.app.xmlui.utils.UIException;
049: import org.dspace.app.xmlui.wing.Message;
050: import org.dspace.authorize.AuthorizeException;
051: import org.dspace.core.Constants;
052: import org.dspace.core.Context;
053: import org.dspace.eperson.EPerson;
054: import org.dspace.eperson.Group;
055:
056: /**
057: * Utility methods to processes actions on Groups. These methods are used
058: * exclusivly from the administrative flow scripts.
059: *
060: * @author scott phillips
061: */
062: public class FlowGroupUtils {
063:
064: /** Language Strings */
065: private static final Message T_edit_group_success_notice = new Message(
066: "default",
067: "xmlui.administrative.FlowGroupUtils.edit_group_success_notice");
068:
069: private static final Message T_delete_group_success_notice = new Message(
070: "default",
071: "xmlui.administrative.FlowGroupUtils.delete_group_success_notice");
072:
073: /**
074: * Return the current name for the given group ID.
075: * @param context The current DSpace context.
076: * @param groupID The group id.
077: * @return The group's name.
078: */
079: public static String getName(Context context, int groupID)
080: throws SQLException {
081: if (groupID < 0)
082: return "New Group";
083:
084: Group group = Group.find(context, groupID);
085:
086: if (group == null)
087: return "New Group";
088:
089: return group.getName();
090: }
091:
092: /**
093: * Return the list of current epeople ID's that are a member of this group.
094: *
095: * @param context The current DSpace context
096: * @param groupID The group's id.
097: * @return An array of ids.
098: */
099: public static String[] getEPeopleMembers(Context context,
100: int groupID) throws SQLException {
101: // New group, just return an empty list
102: if (groupID < 0)
103: return new String[0];
104:
105: Group group = Group.find(context, groupID);
106:
107: if (group == null)
108: return new String[0];
109:
110: EPerson[] epeople = group.getMembers();
111:
112: String[] epeopleIDs = new String[epeople.length];
113: for (int i = 0; i < epeople.length; i++)
114: epeopleIDs[i] = String.valueOf(epeople[i].getID());
115:
116: return epeopleIDs;
117: }
118:
119: /**
120: * Return the list of current group id's that are a member of this group.
121: *
122: * @param context The current DSpace context
123: * @param groupID The group's id.
124: * @return An array of ids.
125: */
126: public static String[] getGroupMembers(Context context, int groupID)
127: throws SQLException {
128: if (groupID < 0)
129: return new String[0];
130:
131: Group group = Group.find(context, groupID);
132:
133: if (group == null)
134: return new String[0];
135:
136: Group[] groups = group.getMemberGroups();
137:
138: String[] groupIDs = new String[groups.length];
139: for (int i = 0; i < groups.length; i++)
140: groupIDs[i] = String.valueOf(groups[i].getID());
141:
142: return groupIDs;
143: }
144:
145: /**
146: * Add the given id to the list and return a new list.
147: *
148: * @param list The current array
149: * @param id The new element
150: * @return A new combined array.
151: */
152: public static String[] addMember(String[] list, String id) {
153: // FIXME: this is terribly ineffecient.
154: List<String> newList = new ArrayList<String>(Arrays
155: .asList(list));
156: newList.add(id);
157: return newList.toArray(new String[newList.size()]);
158: }
159:
160: /**
161: * Remove all instances of the given id from the member list.
162: *
163: * @param list The current array
164: * @param id The id to remove
165: * @return A new combined array.
166: */
167: public static String[] removeMember(String[] list, String id) {
168: // FIXME: this is terribly ineffecient.
169: List<String> newList = new ArrayList<String>(Arrays
170: .asList(list));
171: newList.remove(id);
172: return newList.toArray(new String[newList.size()]);
173: }
174:
175: /**
176: * Save the group. If the name has been changed then it will be updated, if any
177: * members have been added or removed then they are updated.
178: *
179: * If the groupID is -1 then a new group is created.
180: *
181: * @param context The current dspace context
182: * @param groupID The group id, or -1 for a new group.
183: * @param newName The group's new name.
184: * @param newEPeopleIDsArray All epeople members
185: * @param newGroupIDsArray All group members.
186: * @return A result
187: */
188: public static FlowResult processSaveGroup(Context context,
189: int groupID, String newName, String[] newEPeopleIDsArray,
190: String[] newGroupIDsArray) throws SQLException,
191: AuthorizeException, UIException {
192: FlowResult result = new FlowResult();
193:
194: // Decode the name incase it uses non-ascii characters.
195: try {
196: newName = URLDecoder.decode(newName,
197: Constants.DEFAULT_ENCODING);
198: } catch (UnsupportedEncodingException uee) {
199: throw new UIException(uee);
200: }
201:
202: // If the new name is empty we can return in error right away.
203: if (newName == null || newName.length() == 0) {
204: // Group's can not have blank names.
205: result.setContinue(false);
206: result.addError("group_name");
207: result.setOutcome(false);
208: result.setMessage(new Message("default",
209: "The group name may not be blank."));
210:
211: return result;
212: }
213:
214: Group group = null;
215: if (groupID == -1) {
216: // Create a new group, check if the newName is allready in use.
217: Group potentialDuplicate = Group.findByName(context,
218: newName);
219:
220: if (potentialDuplicate == null) {
221: // All good, create the new group.
222: group = Group.create(context);
223: group.setName(newName);
224: } else {
225: // The name is allready in use, return in error.
226: result.setContinue(false);
227: result.addError("group_name");
228: result.addError("group_name_duplicate");
229: result.setOutcome(false);
230: result.setMessage(new Message("default",
231: "The group name is allready in use"));
232:
233: return result;
234: }
235: } else {
236: group = Group.find(context, groupID);
237:
238: // First, check if the name is being updated.
239:
240: String name = group.getName();
241: if (name == null || !name.equals(newName)) {
242: // The group name is to be updated, check if the newName is allready in use.
243: Group potentialDuplicate = Group.findByName(context,
244: newName);
245:
246: if (potentialDuplicate == null) {
247: // All good, update the name
248: group.setName(newName);
249: } else {
250: // The name is allready in use, return in error.
251: result.setContinue(false);
252: result.addError("group_name");
253: result.addError("group_name_duplicate");
254: result.setOutcome(false);
255: result.setMessage(new Message("default",
256: "The group name is allready in use"));
257:
258: return result;
259: }
260: }
261: }
262:
263: // Second, Prepare to check members by turning arrays into lists
264: List<Integer> newEPeopleIDs = new ArrayList<Integer>();
265: for (String epeopleID : newEPeopleIDsArray)
266: newEPeopleIDs.add(Integer.valueOf(epeopleID));
267: List<Integer> newGroupIDs = new ArrayList<Integer>();
268: for (String _groupID : newGroupIDsArray)
269: newGroupIDs.add(Integer.valueOf(_groupID));
270:
271: // Third, check if there are any members to remove
272: // i.e. scan the list on the group against the ids.
273: for (EPerson epersonMember : group.getMembers()) {
274: if (!newEPeopleIDs.contains(epersonMember.getID())) {
275: // The current eperson is not contained in the new list.
276: group.removeMember(epersonMember);
277: } else {
278: // If they are still in the list then remove them
279: // from the list of people to add.
280: newEPeopleIDs.remove((Object) epersonMember.getID());
281: }
282: }
283: for (Group groupMember : group.getMemberGroups()) {
284: if (!newGroupIDs.contains(groupMember.getID())) {
285: // The current group is not contained in the new list.
286: group.removeMember(groupMember);
287: } else {
288: // If they are still in the list then remove them
289: // from the list of groups to add.
290: newGroupIDs.remove((Object) group.getID());
291: }
292: }
293:
294: // Third, check if there are any members to add
295: // i.e. scan the list of ids against the group.
296: for (Integer epersonID : newEPeopleIDs) {
297: EPerson eperson = EPerson.find(context, epersonID);
298:
299: group.addMember(eperson);
300: }
301:
302: for (Integer _groupID : newGroupIDs) {
303: Group _group = Group.find(context, _groupID);
304:
305: group.addMember(_group);
306: }
307:
308: // Last, create the result flow
309: group.update();
310: context.commit();
311:
312: // Let's record our group id incase we created a new one.
313: result.setParameter("groupID", group.getID());
314: result.setContinue(true);
315: result.setOutcome(true);
316: result.setMessage(T_edit_group_success_notice);
317:
318: return result;
319: }
320:
321: /**
322: * Remove the specified groups. It is assumed that the user has allready confirm this selection.
323: *
324: * @param context The current DSpace context
325: * @param groupIDs A list of groups to be removed.
326: * @return A results object.
327: */
328: public static FlowResult processDeleteGroups(Context context,
329: String[] groupIDs) throws SQLException {
330: FlowResult result = new FlowResult();
331: result.setContinue(true);
332:
333: for (String id : groupIDs) {
334: Group groupDeleted = Group.find(context, Integer
335: .valueOf(id));
336: groupDeleted.delete();
337: }
338:
339: result.setOutcome(true);
340: result.setMessage(T_delete_group_success_notice);
341:
342: return result;
343: }
344:
345: /**
346: * The collection prefix, all groups which are specific to
347: * a collection start with this.
348: */
349: private static final String COLLECTION_PREFIX = "COLLECTION_";
350:
351: /**
352: * These are the possible collection suffixes, all groups which are
353: * specific to a collection will end with one of these. The collection
354: * id should be inbetween the prefix and the suffix.
355: */
356: private static final String[] COLLECTION_SUFFIXES = { "_SUBMIT",
357: "_ADMIN", "_WFSTEP_1", "_WORKFLOW_STEP_1", "_WFSTEP_2",
358: "_WORKFLOW_STEP_2", "_WFSTEP_3", "_WORKFLOW_STEP_3",
359: "_DEFAULT_ITEM_READ" };
360:
361: /**
362: * Extracts the collection id that may be immbedded in the given group name.
363: *
364: * @param groupName - the name of a group (ie group.getName())
365: * @return the integer collection id or -1 if the group is not that of a collection
366: */
367: public static int getCollectionId(String groupName) {
368: if (groupName != null
369: && groupName.startsWith(COLLECTION_PREFIX)) {
370: for (String suffix : COLLECTION_SUFFIXES) {
371: if (groupName.endsWith(suffix)) {
372: String idString = groupName
373: .substring(COLLECTION_PREFIX.length());
374: idString = idString.substring(0, idString.length()
375: - suffix.length());
376:
377: int collectionID = -1;
378: try {
379: collectionID = Integer.valueOf(idString);
380:
381: return collectionID;
382: // All good, we were able to ah
383: } catch (NumberFormatException nfe) {
384: // Somethnig went wrong, just ignore the exception and
385: // continue searching for a collection id
386: } // try & catch
387: } // if it ends with a proper suffix.
388: } // for each possible suffix
389: } // if it starts with COLLECTION_
390:
391: return -1;
392: }
393:
394: }
|