diff --git a/dspace-api/src/main/java/org/dspace/app/util/OptimizeSelectCollection.java b/dspace-api/src/main/java/org/dspace/app/util/OptimizeSelectCollection.java new file mode 100644 index 0000000000..c81e20c6ac --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/util/OptimizeSelectCollection.java @@ -0,0 +1,101 @@ +package org.dspace.app.util; + +import org.apache.log4j.Logger; +import org.dspace.content.Collection; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.eperson.EPerson; +import org.springframework.util.StopWatch; + +import java.sql.SQLException; +import java.util.ArrayList; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 3/25/13 + * Time: 2:57 PM + * To change this template use File | Settings | File Templates. + */ +public class OptimizeSelectCollection { + private static final Logger log = Logger.getLogger(OptimizeSelectCollection.class); + private static Context context; + + private static ArrayList brokenPeople; + + public static void main(String[] argv) throws Exception + { + System.out.println("OptimizeSelectCollection tool."); + System.out.println("We want to verify that the optimized version of select collection logic produces the same " + + "values as the legacy select-collection logic."); + + context = new Context(); + brokenPeople = new ArrayList(); + + if(argv != null && argv.length > 0) { + for(String email : argv) { + EPerson person = EPerson.findByEmail(context, email); + checkSelectCollectionForUser(person); + } + } else { + //default case, run as specific user, or run all... + EPerson[] people = EPerson.findAll(context, EPerson.EMAIL); + for(EPerson person : people) { + checkSelectCollectionForUser(person); + } + } + + if(brokenPeople.size() > 0) { + System.out.println("NOT DONE YET!!! Some people don't have all their collections."); + for(EPerson person : brokenPeople) { + System.out.println("-- " + person.getEmail()); + } + } + + } + + private static void checkSelectCollectionForUser(EPerson person) throws SQLException { + context.setCurrentUser(person); + + StopWatch stopWatch = new StopWatch("SelectCollectionStep Optimization (" + person.getEmail() + ")"); + System.out.println("User: " + person.getEmail()); + + stopWatch.start("findAuthorized"); + Collection[] collections = Collection.findAuthorized(context, null, Constants.ADD); + stopWatch.stop(); + + + stopWatch.start("ListingCollections"); + System.out.println("Legacy Find Authorized"); + reportCollections(collections); + stopWatch.stop(); + + stopWatch.start("findAuthorizedOptimized"); + Collection[] collectionsOptimized = Collection.findAuthorizedOptimized(context, Constants.ADD); + stopWatch.stop(); + + stopWatch.start("ListingCollectionsWithOptimizedCollections"); + System.out.println("Find Authorized Optimized"); + reportCollections(collectionsOptimized); + stopWatch.stop(); + + if (collections.length == collectionsOptimized.length) { + System.out.println("Number of collections matches - Good"); + } else { + System.out.println("Number of collections doesn't match -- Bad"); + brokenPeople.add(person); + } + + System.out.println(stopWatch.prettyPrint()); + } + + private static void reportCollections(Collection[] collections) { + System.out.println("===================================="); + System.out.println("This user is permitted to submit to the following collections."); + + for(Collection collection : collections) { + System.out.println(" - " + collection.getHandle() + " -- " + collection.getName()); + } + System.out.println("Total: " + collections.length); + } +} diff --git a/dspace-api/src/main/java/org/dspace/content/Collection.java b/dspace-api/src/main/java/org/dspace/content/Collection.java index 44f6046496..2e70afd7ff 100644 --- a/dspace-api/src/main/java/org/dspace/content/Collection.java +++ b/dspace-api/src/main/java/org/dspace/content/Collection.java @@ -33,10 +33,7 @@ import java.io.InputStream; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.MissingResourceException; +import java.util.*; /** * Class representing a collection. @@ -1505,6 +1502,69 @@ public class Collection extends DSpaceObject myCollections = (Collection[]) myResults.toArray(myCollections); return myCollections; + } + + public static Collection[] findAuthorizedOptimized(Context context, int actionID) throws java.sql.SQLException + { + List myResults = new ArrayList(); + + if(AuthorizeManager.isAdmin(context)) + { + return findAll(context); + } + + //Check eperson->policy + Collection[] directToCollection = findDirectMapped(context, actionID); + for (int i = 0; i< directToCollection.length; i++) + { + if(!myResults.contains(directToCollection[i])) + { + myResults.add(directToCollection[i]); + } + } + + //Check eperson->groups->policy + Collection[] groupToCollection = findGroupMapped(context, actionID); + + for (int i = 0; i< groupToCollection.length; i++) + { + if(!myResults.contains(groupToCollection[i])) + { + myResults.add(groupToCollection[i]); + } + } + + //Check eperson->groups->groups->policy->collection + //i.e. Malcolm Litchfield is a member of OSU_Press_Embargo, + // which is a member of: COLLECTION_24_ADMIN, COLLECTION_24_SUBMIT + Collection[] group2GroupToCollection = findGroup2GroupMapped(context, actionID); + + for (int i = 0; i< group2GroupToCollection.length; i++) + { + if(!myResults.contains(group2GroupToCollection[i])) + { + myResults.add(group2GroupToCollection[i]); + } + } + + //TODO Check eperson->groups->groups->policy->community + + + //TODO Check eperson->groups->policy->community + // i.e. Typical Community Admin -- name.# > COMMUNITY_10_ADMIN > Ohio State University Press + + //Check eperson->comm-admin + + + // Return the collections, sorted alphabetically + Collections.sort(myResults, new CollectionComparator()); + + Collection[] myCollections = new Collection[myResults.size()]; + myCollections = (Collection[]) myResults.toArray(myCollections); + + return myCollections; + + } /** @@ -1609,4 +1669,116 @@ public class Collection extends DSpaceObject ourContext.addEvent(new Event(Event.MODIFY, Constants.COLLECTION, getID(), null, getIdentifiers(ourContext))); } + + //TODO replace hard-coded action_id's with constants... + public static Collection[] findDirectMapped(Context context, int actionID) throws java.sql.SQLException + { + //eperson_id -> resourcepolicy.eperson_id + TableRowIterator tri = DatabaseManager.query(context, + "SELECT * FROM collection, resourcepolicy, eperson " + + "WHERE resourcepolicy.resource_id = collection.collection_id AND " + + "eperson.eperson_id = resourcepolicy.eperson_id AND "+ + "resourcepolicy.resource_type_id = 3 AND "+ + "( resourcepolicy.action_id = 3 OR resourcepolicy.action_id = 11 ) AND "+ + "eperson.eperson_id = ?", context.getCurrentUser().getID()); + return produceCollectionsFromQuery(context, tri); + } + + public static Collection[] findGroupMapped(Context context, int actionID) throws java.sql.SQLException + { + //eperson_id -> resourcepolicy.eperson_id + TableRowIterator tri = DatabaseManager.query(context, + "SELECT * FROM collection, resourcepolicy, eperson, epersongroup2eperson " + + "WHERE resourcepolicy.resource_id = collection.collection_id AND "+ + "eperson.eperson_id = epersongroup2eperson.eperson_id AND "+ + "epersongroup2eperson.eperson_group_id = resourcepolicy.epersongroup_id AND "+ + "resourcepolicy.resource_type_id = 3 AND "+ + "( resourcepolicy.action_id = 3 OR resourcepolicy.action_id = 11 ) AND "+ + "eperson.eperson_id = ?", context.getCurrentUser().getID()); + return produceCollectionsFromQuery(context, tri); + } + + public static Collection[] findGroup2GroupMapped(Context context, int actionID) throws SQLException { + TableRowIterator tri = DatabaseManager.query(context, + "SELECT \n" + + " * \n" + + "FROM \n" + + " public.eperson, \n" + + " public.epersongroup2eperson, \n" + + " public.epersongroup, \n" + + " public.group2group, \n" + + " public.resourcepolicy rp_parent, \n" + + " public.collection\n" + + "WHERE \n" + + " epersongroup2eperson.eperson_id = eperson.eperson_id AND\n" + + " epersongroup.eperson_group_id = epersongroup2eperson.eperson_group_id AND\n" + + " group2group.child_id = epersongroup.eperson_group_id AND\n" + + " rp_parent.epersongroup_id = group2group.parent_id AND\n" + + " collection.collection_id = rp_parent.resource_id AND\n" + + " eperson.eperson_id = ? AND \n" + + " (rp_parent.action_id = 3 OR \n" + + " rp_parent.action_id = 11 \n" + + " ) AND rp_parent.resource_type_id = 3;", context.getCurrentUser().getID()); + return produceCollectionsFromQuery(context, tri); + } + + public static Collection[] findGroup2CommunityMapped(Context context) throws SQLException { + TableRowIterator tri = DatabaseManager.query(context, + "SELECT \n" + + " * \n" + + "FROM \n" + + " public.eperson, \n" + + " public.epersongroup2eperson, \n" + + " public.epersongroup, \n" + + " public.community, \n" + + " public.resourcepolicy\n" + + "WHERE \n" + + " epersongroup2eperson.eperson_id = eperson.eperson_id AND\n" + + " epersongroup.eperson_group_id = epersongroup2eperson.eperson_group_id AND\n" + + " resourcepolicy.epersongroup_id = epersongroup.eperson_group_id AND\n" + + " resourcepolicy.resource_id = community.community_id AND\n" + + " ( resourcepolicy.action_id = 3 OR \n" + + " resourcepolicy.action_id = 11) AND \n" + + " resourcepolicy.resource_type_id = 4 AND eperson.eperson_id = ?", context.getCurrentUser().getID()); + + return produceCollectionsFromCommunityQuery(context, tri); + } + + public static class CollectionComparator implements Comparator { + @Override + public int compare(Collection collection1, Collection collection2) { + return collection1.getName().compareTo(collection2.getName()); + } + } + + public static Collection[] produceCollectionsFromQuery(Context context, TableRowIterator tri) throws SQLException { + List collections = new ArrayList(); + + while(tri.hasNext()) { + TableRow row = tri.next(); + Collection collection = Collection.find(context, row.getIntColumn("collection_id")); + collections.add(collection); + } + + return collections.toArray(new Collection[0]); + } + + public static Collection[] produceCollectionsFromCommunityQuery(Context context, TableRowIterator tri) throws SQLException { + List collections = new ArrayList(); + + while(tri.hasNext()) { + TableRow commRow = tri.next(); + Community community = Community.find(context, commRow.getIntColumn("community_id")); + + Collection[] comCollections = community.getCollections(); + for(Collection collection : comCollections) { + collections.add(collection); + } + + //ugh, handle that communities has subcommunities... + //TODO community.getAllCollections(); + + } + return collections.toArray(new Collection[0]); + } }