/* * EuroCarbDB, a framework for carbohydrate bioinformatics * * Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * A copy of this license accompanies this distribution in the file LICENSE.txt. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * Last commit: $Rev: 1906 $ by $Author: srikalyansswayam $ on $Date:: 2010-03-19 #$ */ package org.eurocarbdb.dataaccess.core; // stdlib imports import java.util.Date; import java.util.HashSet; import java.util.Set; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.Collections; import java.io.Serializable; // 3rd party imports import org.apache.log4j.Logger; import org.hibernate.Query; import org.hibernate.Criteria; import org.hibernate.criterion.*; // eurocarb imports import org.eurocarbdb.dataaccess.Eurocarb; import org.eurocarbdb.dataaccess.Contributed; import org.eurocarbdb.dataaccess.BasicEurocarbObject; // static imports import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; import static org.eurocarbdb.dataaccess.Eurocarb.getEntityManager; /** * A contributor is a person, group, or institution that contributes * data/information to EurocarbDB. * ***** *<h3>Finding the current Contributor</h3> *<pre> * Contributor current = Contributor.getCurrentContributor(); *</pre> * ***** *<h3>Getting the 'guest' Contributor</h3> *<pre> * Contributor guest = Contributor.getGuestContributor(); *</pre> * ***** *<h3>Retrieving or counting objects for a given Contributor</h3> *<p> * The general way of doing this is as follows: *<pre> * // instantiate the appropriate Contributor, eg: * Contributor c = {@link Eurocarb}.getEntityManager().lookup( Contributor.class, id ); * * // count objects of a certain type this Contributor has contributed * // note that this method also counts all contributed *subclasses* of * // the passed class in addition to the passed class. * int count_my_evidence = c.countMyContributionsOf( Evidence.class ); * int count_my_sequences = c.countMyContributionsOf( GlycanSequence.class ); * * // retrieve all these objects, ordered by newest to oldest * // note that this method also retrieves contributed *subclasses* of * // the passed class in addition to the passed class. * List<Evidence> my_evidence = c.getMyContributionsOf( Evidence.class ); * * // or just retrieve a sublist of them, eg: the most recent 10 sequences * List<GlycanSequence> my_evidence = c.getMyContributionsOf( GlycanSequence.class, 10 ); * * // or a pages sublist of them, eg: the 20-29th most recent * List<GlycanSequence> my_evidence = c.getMyContributionsOf( GlycanSequence.class, 10, 20 ); *</pre> * Note also that these method only work with classes that implement the * {@link Contributed} interface (any class that is associatable to a Contributor * should always implement this interface). *</p> ***** * * @see Contributed * @author mjh * edited by @author srikalyan. */ public class Contributor extends BasicEurocarbObject implements Serializable, Comparable<Contributor> { //~~~~~~~~~~~~~~~~~~~~~~ STATIC FIELDS ~~~~~~~~~~~~~~~~~~~~~~~~// /** Query string prefix shortcut */ private static final String Q = "org.eurocarbdb.dataaccess.core.Contributor."; /** Singleton 'guest' contributor @see getGuestContributor() */ private static Contributor Guest = null; /** Logging handle. */ static final Logger log = Logger.getLogger( Contributor.class ); //~~~~~~~~~~~~~~~~~~~~~~~~~~ FIELDS ~~~~~~~~~~~~~~~~~~~~~~~~~~~// /** Database-supplied id for this contributor */ private int contributorId; /** Username of this contributor. */ private String contributorName; /** Login password for this contributor. */ private String password; /** Full name. */ private String fullName; /** Institution */ private String institution; /** OpenId Identifier */ private String openId; /** * email address. */ private String email; /**** * status. */ private Boolean isActivated; /** * last login. */ private Date lastLogin; /**** * is Blocked. */ private Boolean isBlocked; /** True if contributor has administrative rights */ private Boolean isAdmin; /** Date on which this contributor was created in the DB. */ private Date dateEntered; //~~~~~~~~~~~~~~~~~~~~~~ CONSTRUCTORS ~~~~~~~~~~~~~~~~~~~~~~~// /** Default constructor */ public Contributor() { isAdmin = false; } /** Constructor #2 */ public Contributor( String unique_name ) { setContributorName( unique_name ); isAdmin = false; } //~~~~~~~~~~~~~~~~~~~~~~ STATIC METHODS ~~~~~~~~~~~~~~~~~~~~~~~// /* getAllContributors *//************************************** * * Retrieves all contributors from the current data store as * a list. */ @SuppressWarnings("unchecked") public static List<Contributor> getAllContributors() { log.debug("looking up all contributors"); List contributors = getEntityManager() .getQuery( Q + "ALL_CONTRIBUTORS" ) .list(); return (List<Contributor>) contributors; } /* getCurrentContributor *//*********************************** * * Returns the currently active {@link Contributor}, or the * "guest" contributor ({@link #getGuestContributor()}) * if no Contributor is considered active in ("logged into") * the current thread. * * @see #isGuest() * @see Eurocarb.getCurrentContributor() */ public static Contributor getCurrentContributor() { Contributor c = Eurocarb.getCurrentContributor(); if ( c == null ) return getGuestContributor(); return c; } /* getGuestContributor *//************************************* * * Returns the canonical 'guest' Contributor, effectively an * unregistered user. */ public static Contributor getGuestContributor() { if ( Guest != null ) return Guest; log.debug("looking up guest contributor (contributor_id=0)"); Guest = getEntityManager().lookup( Contributor.class, 0 ); if ( Guest == null ) { log.debug("no guest contributor in data store, creating new guest"); Guest = new Contributor("guest"); Guest.setContributorId( 0 ); try { log.debug("no guest contributor (id=0) in data store, creating it..."); getEntityManager().store( Guest ); } catch ( RuntimeException ex ) { log.warn("Caught exception while trying to save 'guest' contributor", ex ); throw ex; } } return Guest; } /* getMapOfGlycanSequenceCountByContributor *//**************** * * Returns a {@link Map} of {@link Contributor}s to the number of {@link GlycanSequence}s * they have contributed. */ public static Map<Contributor,Integer> getMapOfGlycanSequenceCountByContributor() { log.debug("looking up map of contributors by number of glycan sequences contributed"); List<Object[]> result = (List<Object[]>) getEntityManager() .getQuery( Q + "list_contributors_by_count_glycan_sequences_contributed" ) .list(); if ( result == null ) return Collections.emptyMap(); Map<Contributor,Integer> contrib_map = new HashMap<Contributor,Integer>( result.size() ); for ( Object[] row : result ) { contrib_map.put( (Contributor) row[0], (Integer) row[1] ); } return contrib_map; } /* lookupExactName *//***************************************** * * Retrieves a Contributor by their exact name. */ public static Contributor lookupExactName( String name ) { log.debug("looking up contributor by exact name"); Object c = getEntityManager() .getQuery( Q + "BY_EXACT_NAME" ) .setParameter("name", name ) .uniqueResult(); assert c instanceof Contributor; return (Contributor) c; } /* lookupExactEmail *//***************************************** * * Retrieves a Contributor by their exact Email. */ public static Contributor lookupExactEmail( String email ) { log.debug("looking up contributor by exact email"); Object c = getEntityManager() .getQuery( Q + "BY_EXACT_EMAIL" ) .setParameter("email", email ) .uniqueResult(); assert c instanceof Contributor; return (Contributor) c; } /* lookupExactNameNEmail *//***************************************** * * Retrieves a Contributor by their exact Name and Email. */ public static Contributor lookupExactNameNEmail(String name, String email ) { log.debug("looking up contributor by exact name and email"); Object c = getEntityManager() .getQuery( Q + "BY_EXACT_NAME_EMAIL" ) .setParameter("name", name ) .setParameter("email", email ) .uniqueResult(); assert c instanceof Contributor; return (Contributor) c; } /** * Retrieve a contributor by looking them up by their * <a href="http://openid.net">OpenID identifier</a>. */ public static Contributor lookupByIdentifier( String openId ) { log.debug("looking up contributor by openId"); Object c = getEntityManager() .getQuery( Q + "BY_STRING_IDENTIFIER" ) .setParameter("openId", openId ) .uniqueResult(); assert c instanceof Contributor; return (Contributor) c; } //~~~~~~~~~~~~~~~~~~~~~~~~~ METHODS ~~~~~~~~~~~~~~~~~~~~~~~~~~~// /* @see java.lang.Comparable.compareTo */ public int compareTo( Contributor c ) { return this.getContributorName().compareTo( c.getContributorName() ); } /* isAdministrator *//***************************************** * * Returns true if this {@link Contributor} is an Administrator. */ public boolean isAdministrator() { // TODO return isAdmin; } /* isGuest *//************************************************* * * Returns true if this {@link Contributor} is not a registered * user, ie: is a {@link #getGuestContributor() guest}. */ public boolean isGuest() { return this == Guest || getContributorId() == 0 || getContributorName() == "guest"; } /* isLoggedIn *//********************************************** * * Returns true if this contributor is the active ("logged in") * Contributor for the current {@link Thread} -- Note that the * "guest" Contributor is NOT regarded as logged in, and hence * returns false from this method. */ public boolean isLoggedIn() { return (this.isGuest()) ? false : this.equals( getCurrentContributor() ); } /* getContributorId *//**************************************** * * Returns this Contributor's unique (numerical) id. */ public int getContributorId() { return this.contributorId; } /** Internal use only */ protected void setContributorId( int contributorId ) { this.contributorId = contributorId; } /** * Returns this Contributor's unique (user-given) name. */ public String getContributorName() { return this.contributorName; } /** * Sets this Contributor's unique (user-given) name. * @throws IllegalArgumentException if the given name * would break the uniqueness requirement of contributor names. */ public void setContributorName( String name ) throws IllegalArgumentException { // TODO - lookup name in DB before assigning this.contributorName = name; } /** Returns the full name of this Contributor. */ public String getFullName() { return this.fullName; } /** * Sets the full name of this Contributor. */ public void setFullName( String fullName ) { this.fullName = fullName; } /** Returns the institution of this Contributor. */ public String getInstitution() { return this.institution; } /** * Sets the institution of this Contributor. */ public void setInstitution( String institution ) { this.institution = institution; } /** Returns the openId of this Contributor. */ public String getOpenId() { return this.openId; } /** * Sets the openId of this Contributor. */ public void setOpenId( String openId ) { this.openId = openId; } /** Returns the password for this Contributor. */ public String getPassword() { return this.password; } /** * Sets the password for this Contributor. */ public void setPassword( String password ) { this.password = password; } /** Return true if the user has administrative rights */ public Boolean getIsAdmin() { return this.isAdmin; } /** Set the flag indicating if the user has administrative rights */ public void setIsAdmin(Boolean f) { this.isAdmin = f; } /** Returns the {@link Date} this Contributor was created. */ public Date getDateEntered() { return this.dateEntered; } /** * Sets the {@link Date} this Contributor was created * (privileged operation). */ public void setDateEntered( Date dateEntered ) { this.dateEntered = dateEntered; } /** * gets the email address of the contributor. * */ public String getEmail() { return email; } /*** * sets the email address of the contributor. * */ public void setEmail(String email) { this.email = email; } /** * gets the activation status of the contributor. * */ public Boolean getIsActivated() { return isActivated; } /** * sets the activation status of the contributor. * @param isActivated */ public void setIsActivated(Boolean isActivated) { this.isActivated = isActivated; } /*** * gets the blocked status of the contributor. * */ public Boolean getIsBlocked() { return isBlocked; } /*** * sets the blocked status of the contributor. * @param isBlocked */ public void setIsBlocked(Boolean isBlocked) { this.isBlocked = isBlocked; } /*** * gets the last login date of the contributor. * */ public Date getLastLogin() { return lastLogin; } /*** * sets the last login date of the contributor. */ public void setLastLogin(Date lastLogin) { this.lastLogin = lastLogin; } /*** * gets the number of inactive unblocked contributors. * */ public int getNumberOfInactiveContributors() { List<Contributor> temp= getInactiveContributors(); return temp==null?-1:temp.size(); } /*** * gets the list of inactive unblocked contributors. */ public List<Contributor> getInactiveContributors() { return isAdmin?(List<Contributor>)getEntityManager().getQuery(Q + "ALL_INACTIVE_CONTRIBUTORS").list():null; } /*** * gets the list of contributors who are active and are admins. * @return list of contributors who are admins. */ public List<Contributor> getAllActiveNonAdmins() { return isAdmin?(List<Contributor>) Eurocarb.getEntityManager().getQuery(Q + "ACTIVE_CONTRIBUTORS_NON_ADMINS").list():null; } /*** * gets a list of all active Admin except the current Admin. * @return */ public List<Contributor> getAllActiveAdminsExceptCurrent() { //log.debug("current contributor name is "+contributorName); return isAdmin?(List<Contributor>) Eurocarb.getEntityManager().getQuery(Q + "ACTIVE_ADMINISTRATORS_NOT_CURRENT").setParameter("current", contributorName).list():null; } /***** * get the list of unblocked contributors who are not admins. * coz you cannot block admins. if you want demote them and unblock them. * @return */ public List<Contributor> getAllActiveUnblockedContributors() { return isAdmin?(List<Contributor>) Eurocarb.getEntityManager().getQuery(Q + "ACTIVE_CONTRIBUTORS_NON_ADMINS").list():null; } /*** * gets the list of the all blocked contributors. * @return */ public List<Contributor> getAllBlockedContributors() { return isAdmin?(List<Contributor>) Eurocarb.getEntityManager().getQuery(Q + "ALL_BLOCKED_CONTRIBUTORS").list():null; } // Query-driven methods //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public <T extends Contributed> Integer countMyContributionsOf( Class<T> c ) { /* TODO: this has to be done with Criteria query */ // int id = this.getContributorId(); Object result = getEntityManager() .createQuery( c ) .setComment( this.getClass().getName() + ".countMyContributionsOf") .add( Restrictions.eq( "contributor", this ) ) .setProjection( Projections.rowCount() ) .uniqueResult() ; if ( result == null ) return 0; assert result instanceof Integer; return (Integer) result; } /** * Convenience method for counting all the current {@link Contributor}'s * {@link GlycanSequence}s. Equivalent to calling the following: *<pre> * countMyContributionsOf( GlycanSequence.class ) *</pre>. */ public Integer countMyGlycanSequences() { return countMyContributionsOf( GlycanSequence.class ); } /** * Returns a sub-{@link List} of the requested object type, ordered by most recent first, * of objects that this {@link Contributor} has contributed. The size of the list * will be equal to the value of Eurocarb.getProperty("pref.show_max_recent_items"), * or 100 if not defined. * * @see #getMyContributionsOf(Class,int,int) */ public <T extends Contributed> List<T> getMyContributionsOf( Class<T> c ) { int limit = Eurocarb.getProperty("pref.show_max_recent_items", Integer.class ); return getMyContributionsOf( c, limit, 0 ); } /** * Returns a sub-{@link List} of the requested object type, ordered by most recent first, * of objects that this {@link Contributor} has contributed. * * @see #getMyContributionsOf(Class,int,int) */ public <T extends Contributed> List<T> getMyContributionsOf( Class<T> c, int limit ) { return getMyContributionsOf( c, limit, 0 ); } /** * Returns a sub-{@link List} of the requested object type, ordered by most recent first, * of objects that this {@link Contributor} has contributed, limited by the given * limit and index. * * @param c * The class of the object type requested. * @param limit * The max number of objects to return. * @param index * Index into the sub-list of the Contributor's total contributions. */ @SuppressWarnings("unchecked") public <T extends Contributed> List<T> getMyContributionsOf( Class<T> c, int limit, int index ) { // int id = this.getContributorId(); Criteria q = getEntityManager() .createQuery( c ) .add( Restrictions.eq( "contributor", this ) ) .addOrder( Order.desc("dateEntered") ) // .setMaxResults( limit ) // .setFirstResult( index ) ; if ( limit > 0 ) { q.setMaxResults( limit ); } if ( index > 0 ) { q.setFirstResult( index ); } Object result = q.list(); if ( result == null ) return Collections.emptyList(); return (List<T>) result; } /* getMyBiologicalContexts *//********************************* * * Returns all {@link BiologicalContext}s this {@link Contributor} * has ever contributed. */ @SuppressWarnings("unchecked") public List<BiologicalContext> getMyBiologicalContexts() { int id = this.getContributorId(); assert id > 0; if ( log.isDebugEnabled() ) log.debug("looking up all BiologicalContexts for Contributor=" + id ); List<BiologicalContext> list; list = (List<BiologicalContext>) getEntityManager() .getQuery( Q + "GET_ALL_CONTRIBUTED_CONTEXTS_BY_ID" ) .setParameter("id", id ) .list(); if ( list == null ) return emptyList(); return list; } /* getMyTaxonomies *//********************************* * * Returns all {@link Taxonomy}s this {@link Contributor} * has ever linked to. */ @SuppressWarnings("unchecked") public List<Taxonomy> getMyTaxonomies() { int id = this.getContributorId(); assert id > 0; if ( log.isDebugEnabled() ) log.debug("looking up all Taxonomies for Contributor=" + id ); List<Taxonomy> list; list = (List<Taxonomy>) getEntityManager() .getQuery( Q + "GET_ALL_CONTRIBUTED_TAXONOMIES_BY_ID" ) .setParameter("id", id ) .list(); if ( list == null ) return emptyList(); return list; } /* getMyTissueTaxonomies *//********************************* * * Returns all {@link TissueTaxonomy}s this {@link Contributor} * has ever linked to. */ @SuppressWarnings("unchecked") public List<TissueTaxonomy> getMyTissueTaxonomies() { int id = this.getContributorId(); assert id > 0; if ( log.isDebugEnabled() ) log.debug("looking up all TissueTaxonomies for Contributor=" + id ); List<TissueTaxonomy> list; list = (List<TissueTaxonomy>) getEntityManager() .getQuery( Q + "GET_ALL_CONTRIBUTED_TISSUETAXONOMIES_BY_ID" ) .setParameter("id", id ) .list(); if ( list == null ) return emptyList(); return list; } /* getMyDiseases *//********************************* * * Returns all {@link Disease}s this {@link Contributor} * has ever linked to. */ @SuppressWarnings("unchecked") public List<Disease> getMyDiseases() { int id = this.getContributorId(); assert id > 0; if ( log.isDebugEnabled() ) log.debug("looking up all Diseases for Contributor=" + id ); List<Disease> list; list = (List<Disease>) getEntityManager() .getQuery( Q + "GET_ALL_CONTRIBUTED_DISEASES_BY_ID" ) .setParameter("id", id ) .list(); if ( list == null ) return emptyList(); return list; } /* getMyPerturbations *//********************************* * * Returns all {@link Perturbation}s this {@link Contributor} * has ever linked to. */ @SuppressWarnings("unchecked") public List<Perturbation> getMyPerturbations() { int id = this.getContributorId(); assert id > 0; if ( log.isDebugEnabled() ) log.debug("looking up all Perturbations for Contributor=" + id ); List<Perturbation> list; list = (List<Perturbation>) getEntityManager() .getQuery( Q + "GET_ALL_CONTRIBUTED_PERTURBATIONS_BY_ID" ) .setParameter("id", id ) .list(); if ( list == null ) return emptyList(); return list; } /* getMyRecentGlycanSequences *//************************************ * * Returns the given number of {@link GlycanSequence}s that have been * contributed by this {@link Contributor}; most recent first. */ @SuppressWarnings("unchecked") public List<GlycanSequence> getMyRecentGlycanSequences( int count ) { return getMyContributionsOf( GlycanSequence.class, count ); } /* getMyEvidence *//******************************************* * * Returns all {@link Evidence} this {@link Contributor} * has ever contributed. */ @SuppressWarnings("unchecked") public List<Evidence> getMyEvidence() { int id = this.getContributorId(); assert id > 0; if ( log.isDebugEnabled() ) log.debug("looking up all Evidence for Contributor=" + id ); List<Evidence> list; list = (List<Evidence>) getEntityManager() .getQuery( Q + "GET_ALL_CONTRIBUTED_EVIDENCE_BY_ID" ) .setParameter("id", id ) .list(); if ( list == null ) return emptyList(); return list; } /* getMyExperiments *//**************************************** * * Returns all {@link Experiment}s this {@link Contributor} * has ever contributed. */ @SuppressWarnings("unchecked") public List<Experiment> getMyExperiments() { int id = this.getContributorId(); assert id > 0; if ( log.isDebugEnabled() ) log.debug("looking up all Experiments for Contributor=" + id ); List<Experiment> list; list = (List<Experiment>) getEntityManager() .getQuery( Q + "GET_ALL_CONTRIBUTED_EXPERIMENTS_BY_ID" ) .setParameter("id", id ) .list(); if ( list == null ) return emptyList(); return list; } /* getMyRecentContributions *//******************************** * * Returns the requested number of {@link Contributed} objects * this {@link Contributor} has contributed, ordered by most to * least recent, or an empty list if this contributor has not * contributed anything. * * TODO: this method has issues due to Hibernate's brain-dead * polymorphic queries not being able to accept setMaxResults * so it tries to load and sort entire tables.... */ @SuppressWarnings("unchecked") public List<Contributed> getMyRecentContributions( int max_count ) { int id = this.getContributorId(); if ( id <= 0 ) throw new UnsupportedOperationException( "Cannot execute method, contributor_id is <= 0"); log.debug("looking up all Contributed objects for contributor_id=" + id ); List<Contributed> changes = (List<Contributed>) getEntityManager() .getQuery( Q + "GET_RECENT_BY_CONTRIBUTOR") .setParameter("contributor_id", id ) .setMaxResults( max_count ) .list(); if ( changes == null ) { log.debug("(no rows received)"); return Collections.emptyList(); } return changes; } /* getMyUniqueBiologicalContexts *//*************************** * * Returns all unique {@link BiologicalContext}s this * {@link Contributor} has ever contributed. */ @SuppressWarnings("unchecked") public Set<BiologicalContext> getMyUniqueBiologicalContexts() { List<BiologicalContext> bclist = getMyBiologicalContexts(); if ( bclist.size() == 0 ) return emptySet(); // TODO Set<BiologicalContext> bcset = new HashSet<BiologicalContext>( bclist.size() ); bcset.addAll( bclist ); return bcset; } /** Returns {@link getContributorName()}. */ public String getName() { return getContributorName(); } /* hashCode *//************************************************ * * Returns a hashCode based on {@link getContributorId() contributorId} * and {@link getContributorName() contributorName}. */ public int hashCode() { return ( contributorId + ':' + contributorName ).hashCode(); } /* equals *//************************************************** * * Compares equality by value of {@link getContributorId() contributorId} * and {@link getContributorName() contributorName}. */ public boolean equals( Object x ) { if ( this == x ) return true; if ( (x == null) || ! (x instanceof Contributor) ) return false; // objects are the same class Contributor c = (Contributor) x; return this.getContributorId() == c.getContributorId() && this.getContributorName() == c.getContributorName(); } } // end class