Changeset 5167


Ignore:
Timestamp:
Oct 28, 2009, 2:16:26 PM (12 years ago)
Author:
Nicklas Nordborg
Message:

Fixes #1377: Filter item lists on the 'Shared to' column

The "Project items" and the "All items" lists can now also be used with "Shared to" filter. This required some major reorganization of the code in the AbstractEntityQuery code. The new class AbstractHqlQuery contains all HQL stuff that is useful for almost any type of HQL query. The old class is for queries that return a single type of entities.

Location:
trunk
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/core/net/sf/basedb/core/AbstractEntityQuery.java

    r4889 r5167  
    2626import net.sf.basedb.core.query.EntityQuery;
    2727import net.sf.basedb.core.query.JoinType;
    28 import net.sf.basedb.core.query.QueryParameter;
    2928import net.sf.basedb.core.query.Select;
    3029import net.sf.basedb.core.query.Expression;
     
    3332import net.sf.basedb.core.query.Hql;
    3433import net.sf.basedb.core.query.QueryType;
    35 import net.sf.basedb.core.signal.SignalException;
    36 
    37 import java.util.Set;
    38 import java.util.Map;
    39 import java.util.Collections;
     34
    4035import java.util.Collection;
    4136import java.util.EnumSet;
    42 
    43 import org.hibernate.Query;
    4437
    4538/**
     
    5548*/
    5649abstract class AbstractEntityQuery
    57   extends AbstractQuery
     50  extends AbstractHqlQuery
    5851  implements EntityQuery
    5952{
     
    8477 
    8578  /**
    86     If the query should be executed in a stateless session or not.
    87   */
    88   private final boolean stateless;
    89  
    90   /**
    9179    The required runtime filter.
    9280  */
     
    10290  */
    10391  private QueryRuntimeFilterManager filterManager;
    104  
    105   /**
    106     The most recent DbControl used to execute the main query.
    107   */
    108   private DbControl lastMainDc;
    109 
    110   /**
    111     The most recent DbControl used to execute the count query.
    112   */
    113   private DbControl lastCountDc;
    114  
    115   /**
    116     The most recent main query.
    117   */
    118   private org.hibernate.Query lastMainQuery;
    119  
    120   /**
    121     The most recent count query.
    122   */
    123   private org.hibernate.Query lastCountQuery;
    124  
    125   /**
    126     If the results should be cached or not.
    127   */
    128   private boolean cacheResults;
    12992 
    13093  /**
     
    178141      boolean stateless, QueryRuntimeFilter optionalFilter)
    179142  {
    180     super(rootName == null ? rootType.getDataClass().getName() : rootName);
     143    super(rootName == null ? rootType.getDataClass().getName() : rootName, rootType.getAlias(), stateless);
    181144    super.selectPermanent(Selects.expression(Hql.property(rootType.getAlias(), select), null, true));
    182145    this.returnType = returnType;
    183146    this.rootType = rootType;
    184     this.stateless = stateless;
    185147    this.requiredFilter = QueryRuntimeFilterFactory.getRequiredFilter(rootType);
    186148    this.optionalFilter = optionalFilter;
     
    199161    @throws UnsupportedOperationException Always
    200162  */
     163  @Override
    201164  public void select(Select select)
    202165  {
     
    207170    @throws UnsupportedOperationException Always
    208171  */
     172  @Override
    209173  public void selectPermanent(Select select)
    210174  {
     
    216180    @throws UnsupportedOperationException Always
    217181  */
     182  @Override
    218183  public void group(Expression expression)
    219184  {
     
    224189    @throws UnsupportedOperationException Always
    225190  */
     191  @Override
    226192  public void groupPermanent(Expression expression)
    227193  {
     
    233199    @throws UnsupportedOperationException Always
    234200  */
     201  @Override
    235202  public void having(Restriction restriction)
    236203  {
     
    241208    @throws UnsupportedOperationException Always
    242209  */
     210  @Override
    243211  public void havingPermanent(Restriction restriction)
    244212  {
     
    249217    @return {@link QueryType#HQL}
    250218  */
     219  @Override
    251220  public QueryType getQueryType()
    252221  {
     
    254223  }
    255224 
    256   /**
    257     The alias of the item that is the root of this query.
    258     @see Item#getAlias()
    259   */
    260   public String getRootAlias()
    261   {
    262     return rootType.getAlias();
    263   }
    264  
    265   public boolean isReadonly()
    266   {
    267     return super.isReadonly() || lastMainQuery != null;
    268   }
    269  
    270   /**
    271     Reset all non-permanent query elements of the query and
    272     clear cached queries.
    273   */
    274   public void reset()
    275   {
    276     super.reset();
    277     lastMainQuery = null;
    278     lastCountQuery = null;
    279     lastMainDc = null;
    280     lastCountDc = null;
    281   }
     225
     226  @Override
    282227  public long count(DbControl dc)
    283228    throws BaseException
     
    287232    try
    288233    {
    289       Query query = getCountHqlQuery(dc);
    290       count = isStateless() ?
    291         QueryExecutor.loadData(Long.class, query, dc.getStatelessSession(), dc.getSessionControl()) :
    292         HibernateUtil.loadData(Long.class, query);
    293     }
    294     catch (InterruptedException ex)
    295     {
    296       throw new SignalException("Aborted by user", ex);
     234      count = super.count(dc);
    297235    }
    298236    finally
     
    303241  }
    304242  // -------------------------------------------
    305   /*
    306     From the HqlQuery interface
    307     -------------------------------------------
    308   */
    309   public void setCacheResult(boolean flag)
    310   {
    311     this.cacheResults = flag;
    312   }
    313   public boolean isCachingResult()
    314   {
    315     return cacheResults;
    316   }
    317   // -------------------------------------------
    318  
     243
    319244  /*
    320245    From the EntityQuery interface
    321246    -------------------------------------------
    322247  */
     248  @Override
    323249  public Item getItemType()
    324250  {
     
    328254    @since 2.8
    329255  */
     256  @Override
    330257  public Item getRootType()
    331258  {
    332259    return rootType;
    333260  }
     261  @Override
    334262  public void include(Include... includes)
    335263  {
     
    339267    }
    340268  }
     269  @Override
    341270  public void include(Collection<Include> includes)
    342271  {
    343272    this.includes.addAll(includes);
    344273  }
     274  @Override
    345275  public void exclude(Include... excludes)
    346276  {
     
    350280    }
    351281  }
     282  @Override
    352283  public void exclude(Collection<Include> includes)
    353284  {
    354285    this.includes.removeAll(includes);
    355286  }
     287  @Override
    356288  public boolean isIncluded(Include... includes)
    357289  {
     
    363295    return isIncluded;
    364296  }
     297  @Override
    365298  public boolean isIncluded(Collection<Include> includes)
    366299  {
    367300    return this.includes.containsAll(includes);
    368301  }
     302  @Override
    369303  public void setItemPermission(Permission permission)
    370304  {
    371305    this.permission = permission == null ? Permission.READ : permission;
    372306  }
     307  @Override
    373308  public Permission getItemPermission()
    374309  {
     
    390325 
    391326  /**
    392     Build the main query and set parameter values for it. If the query has been
    393     executed with the same <code>DbControl</code> before and hasn't been {@link #reset()}
    394     the cached query is returned. If the parameters values have been changed the new
    395     values are used.
    396    
    397     @param dc The DbControl to use for executing the query
    398     @return A <code>org.hibernate.Query</code> object
    399   */
    400   org.hibernate.Query getMainHqlQuery(DbControl dc)
    401   {
    402     if (lastMainQuery == null || lastMainDc != dc)
    403     {
    404       // If we are using the same DbControl as before we don't have to rebuild the query
    405       String mainHql = getMainQuery(dc, true);
    406       if (stateless)
    407       {
    408         lastMainQuery =  HibernateUtil.createQuery(dc.getStatelessSession(), mainHql);
    409       }
    410       else
    411       {
    412         lastMainQuery =  HibernateUtil.createQuery(dc.getHibernateSession(), mainHql);
    413       }
    414     }
    415     lastMainDc = dc;
    416     lastMainQuery.setCacheable(isCachingResult());
    417     setParameters(lastMainQuery, getParameters());
    418     if (getFirstResult() >= 0) lastMainQuery.setFirstResult(getFirstResult());
    419     if (getMaxResults() > 0) lastMainQuery.setMaxResults(getMaxResults());
    420     return lastMainQuery;
    421   }
    422  
    423   /**
    424     Build the count query and set parameter values for it. If the query has been
    425     executed with the same <code>DbControl</code> before and hasn't been {@link #reset()}
    426     the cached query is returned. If the parameters values have been changed the new
    427     values are used.
    428    
    429     @param dc The DbControl to use for executing the query
    430     @return A <code>org.hibernate.Query</code> object
    431   */
    432   org.hibernate.Query getCountHqlQuery(DbControl dc)
    433   {
    434     if (lastCountQuery == null || lastCountDc != dc)
    435     {
    436       // If we are using the same DbControl as before we don't have to rebuild the query
    437       String countHql = getCountQuery(dc, true);
    438       if (stateless)
    439       {
    440         lastCountQuery =  HibernateUtil.createQuery(dc.getStatelessSession(), countHql);
    441       }
    442       else
    443       {
    444         lastCountQuery =  HibernateUtil.createQuery(dc.getHibernateSession(), countHql);
    445       }
    446     }
    447     lastCountDc = dc;
    448     lastCountQuery.setCacheable(true);
    449     setParameters(lastCountQuery, getParameters());
    450     return lastCountQuery;
    451   }
    452  
    453   /**
    454     If queries are using the stateless Hibernate session or the regular
    455     session.
    456     @return TRUE if the stateless session is used, FALSE otherwise
    457     @since 2.4
    458   */
    459   protected boolean isStateless()
    460   {
    461     return stateless;
    462   }
    463  
    464   /**
    465327    Enable runtime query filters for the query.
    466328    @see #disableFilters(DbControl)
     
    488350    }
    489351  }
    490  
    491   private static final Set<Integer> ZERO_SET = Collections.singleton(0);
    492 
    493   /**
    494     Set parameter values on a query.
    495     @param query The Hibernate query object
    496     @param parameters A map containing parameter names and values
    497   */
    498   private void setParameters(org.hibernate.Query query, Map<String, QueryParameter> parameters)
    499   {
    500     if (parameters == null) return;
    501     if (debugEnabled)
    502     {
    503       logParam.debug("Binding parameters to query: " + query.getQueryString());
    504     }
    505     for (Map.Entry<String, QueryParameter> entry : parameters.entrySet())
    506     {
    507       String name = entry.getKey();
    508       QueryParameter qp = entry.getValue();
    509       Type valueType = qp.getType();
    510       Object value = qp.getValue();
    511       if (value instanceof Collection)
    512       {
    513         Collection c = (Collection)value;
    514         if (debugEnabled)
    515         {
    516           logParam.debug("Binding collection '"+value+"' to parameter :"+name);
    517         }
    518         if (valueType == null)
    519         {
    520           query.setParameterList(name, c.size() == 0 ? ZERO_SET : c);
    521         }
    522         else
    523         {
    524           query.setParameterList(name, c.size() == 0 ? ZERO_SET : c, valueType.getHibernateType());
    525         }
    526       }
    527       else
    528       {
    529         if (debugEnabled)
    530         {
    531           logParam.debug("Binding '"+value+"' to parameter :"+name);
    532         }
    533         if (valueType == null)
    534         {
    535           query.setParameter(name, value);
    536         }
    537         else
    538         {
    539           query.setParameter(name, value, valueType.getHibernateType());
    540         }
    541       }
    542     }
    543   }
    544352
    545353}
  • trunk/src/core/net/sf/basedb/core/Project.java

    r4889 r5167  
    2929import net.sf.basedb.core.data.ProjectData;
    3030import net.sf.basedb.core.data.ShareableData;
     31import net.sf.basedb.core.query.Restriction;
    3132import net.sf.basedb.core.query.Restrictions;
    3233import net.sf.basedb.core.query.Hql;
    3334import net.sf.basedb.core.query.EntityQuery;
    3435import net.sf.basedb.core.query.ResultList;
     36import net.sf.basedb.core.query.Selects;
    3537import net.sf.basedb.info.ProjectInfo;
    3638import net.sf.basedb.info.ToTransferable;
     
    451453  {
    452454    return getItems(itemType == null ? null : Collections.singleton(itemType),
    453         firstItem, maxItems, permission, null);
     455        firstItem, maxItems, permission, null, null);
    454456  }
    455457 
     
    462464  {
    463465    return getItems(itemType == null ? null : Collections.singleton(itemType),
    464       firstItem, maxItems, permission, include);
    465   }
     466      firstItem, maxItems, permission, include, null);
     467  }
     468 
     469  /**
     470    @since 2.7.1
     471    @deprecated In 2.15, use {@link #getItems(Set, int, int, Permission, Set, Restriction)}
     472      instead
     473  */
     474  public ResultList<Shareable> getItems(Set<Item> itemTypes, int firstItem, int maxItems,
     475      Permission permission, Set<Include> include)
     476  {
     477    return getItems(itemTypes, firstItem, maxItems, permission, include, null);
     478  }
     479
    466480 
    467481  /**
     
    477491    @param include Options for which items that should be included/excluded from the
    478492      result, or null to include all non-removed items
     493    @param restriction An optional restriction that is applied to the
     494      queries to further reduce the list
    479495    @return A list containing shareable items
    480496    @see SessionControl#setActiveProject(Project)
    481     @since 2.7.1
     497    @since 2.15
    482498  */
    483499  public ResultList<Shareable> getItems(Set<Item> itemTypes, int firstItem, int maxItems,
    484     Permission permission, Set<Include> include)
     500    Permission permission, Set<Include> include, Restriction restriction)
    485501  {
    486502    if (include == null) include = EnumSet.of(Include.NOT_REMOVED, Include.MINE, Include.OTHERS);
     
    569585        if (ShareableData.class.isAssignableFrom(item.getDataClass()))
    570586        {
    571           org.hibernate.Query query = HibernateUtil.createQuery(session,
    572             "SELECT shared FROM " + item.getDataClass().getName() + " shared ");
    573           inProject.addAll(HibernateUtil.loadList(ShareableData.class, query, sc));
     587          // Query to load all shareable items of a specific subclass
     588          AbstractHqlQuery hql =
     589            new AbstractHqlQuery(item.getDataClass().getName(), "item", false){};
     590          hql.select(Selects.expression(Hql.alias("item"), null, true));
     591          if (restriction != null) hql.restrict(restriction);
     592          /*
     593            SELECT item
     594            FROM <class> item
     595            [WHERE restriction]
     596          */
     597          inProject.addAll(HibernateUtil.loadList(ShareableData.class, hql.getMainHqlQuery(dc), sc));
    574598        }
    575599      }
     
    578602    {
    579603      // Query to load all shareable items
    580       org.hibernate.Query query = HibernateUtil.getPredefinedQuery(session, "GET_SHARED_ITEMS");
     604      AbstractHqlQuery hql =
     605        new AbstractHqlQuery("net.sf.basedb.core.data.ShareableData", "item", false){};
     606      hql.select(Selects.expression(Hql.alias("item"), null, true));
     607      if (restriction != null) hql.restrict(restriction);
    581608      /*
    582609        SELECT item
    583610        FROM net.sf.basedb.core.data.ShareableData item
     611        [WHERE restriction]
    584612      */
    585       inProject = HibernateUtil.loadList(ShareableData.class, query, sc);
     613      inProject = HibernateUtil.loadList(ShareableData.class, hql.getMainHqlQuery(dc), sc);
    586614    }
    587615    // Disable filters
  • trunk/src/core/net/sf/basedb/core/User.java

    r4889 r5167  
    3333import net.sf.basedb.core.data.DirectoryData;
    3434import net.sf.basedb.util.MD5;
     35import net.sf.basedb.core.query.Restriction;
    3536import net.sf.basedb.core.query.Restrictions;
    3637import net.sf.basedb.core.query.Hql;
    3738import net.sf.basedb.core.query.EntityQuery;
    3839import net.sf.basedb.core.query.ResultList;
     40import net.sf.basedb.core.query.Selects;
    3941
    4042import java.util.ArrayList;
     
    10961098 
    10971099  /**
     1100    @since 2.7.1
     1101    @deprecated In 2.15, use {@link #getItems(Set, int, int, Permission, Restriction)} instead
     1102  */
     1103  public ResultList<Ownable> getItems(Set<Item> itemTypes, int firstItem, int maxItems, Permission permission)
     1104  {
     1105    return getItems(itemTypes, firstItem, maxItems, permission, null);
     1106  }
     1107
     1108 
     1109  /**
    10981110    Load the items owned by this user. If this user is not the same as the
    10991111    currently logged in user this method will only load items that are
     
    11061118    @param permission The permission the logged in user should have on
    11071119      the items
     1120    @param restriction An optional restriction that is applied to the
     1121      queries to further reduce the list
    11081122    @return A list containing ownable items
    1109     @since 2.7.1
    1110   */
    1111   public ResultList<Ownable> getItems(Set<Item> itemTypes, int firstItem, int maxItems, Permission permission)
     1123    @since 2.15
     1124  */
     1125  public ResultList<Ownable> getItems(Set<Item> itemTypes, int firstItem, int maxItems,
     1126    Permission permission, Restriction restriction)
    11121127  {
    11131128    DbControl dc = getDbControl();
     
    11501165        if (OwnableData.class.isAssignableFrom(item.getDataClass()))
    11511166        {
    1152           org.hibernate.Query query = HibernateUtil.createQuery(session,
    1153             "SELECT owned FROM " + item.getDataClass().getName() + " owned " +
    1154             "WHERE owned.owner = :user");
    1155           query.setEntity("user", this.getData());
    1156           ownedBy.addAll(HibernateUtil.loadList(OwnableData.class, query, sc));
     1167          // Query to load all ownable items of a specific subclass
     1168          AbstractHqlQuery hql =
     1169            new AbstractHqlQuery(item.getDataClass().getName(), "item", false){};
     1170          hql.select(Selects.expression(Hql.alias("item"), null, true));
     1171          hql.restrict(Hql.restriction("item.owner = :user", null));
     1172          hql.setParameter("user", getId(), Type.INT);
     1173          if (restriction != null) hql.restrict(restriction);
     1174          /*
     1175            SELECT item
     1176            FROM <class> item
     1177            WHERE item.owner = :user
     1178            [AND restriction]
     1179          */
     1180          ownedBy.addAll(HibernateUtil.loadList(OwnableData.class, hql.getMainHqlQuery(dc), sc));
    11571181        }
    11581182      }
     
    11601184    else
    11611185    {
    1162       org.hibernate.Query query = HibernateUtil.getPredefinedQuery(session,
    1163         "GET_OWNABLE_ITEMS_FOR_USER");
     1186      AbstractHqlQuery hql =
     1187        new AbstractHqlQuery("net.sf.basedb.core.data.OwnableData", "item", false){};
     1188      hql.select(Selects.expression(Hql.alias("item"), null, true));
     1189      hql.restrict(Hql.restriction("item.owner = :user", null));
     1190      hql.setParameter("user", getId(), Type.INT);
     1191      if (restriction != null) hql.restrict(restriction);
    11641192      /*
    1165         SELECT o
    1166         FROM net.sf.basedb.core.data.OwnableData o
    1167         WHERE o.owner = :user
     1193        SELECT item
     1194        FROM net.sf.basedb.core.data.OwnableData item
     1195        WHERE item.owner = :user
     1196        [AND restriction]
    11681197      */
    1169       query.setEntity("user", this.getData());
    1170       ownedBy = HibernateUtil.loadList(OwnableData.class, query, sc);
     1198      ownedBy = HibernateUtil.loadList(OwnableData.class, hql.getMainHqlQuery(dc), sc);
    11711199    }
    11721200    // Disable filters
  • trunk/src/test/TestProject.java

    r4889 r5167  
    494494      dc = TestUtil.getDbControl();
    495495      Project p = Project.getById(dc, id);
    496       List<Shareable> l = p.getItems((Set<Item>)null, 0, 0, null, null);
     496      List<Shareable> l = p.getItems((Set<Item>)null, 0, 0, null, null, null);
    497497      for (int i = 0; i<l.size(); i++)
    498498      {
  • trunk/www/my_base/projects/items/list_items.jsp

    r4889 r5167  
    4040  import="net.sf.basedb.core.Directory"
    4141  import="net.sf.basedb.core.Metadata"
     42  import="net.sf.basedb.core.PropertyFilter"
    4243  import="net.sf.basedb.core.query.ResultList"
     44  import="net.sf.basedb.core.query.Restriction"
    4345  import="net.sf.basedb.util.Enumeration"
    4446  import="net.sf.basedb.util.ShareableUtil"
     
    99101      }
    100102    }
     103    PropertyFilter sharedToFilter = cc.getPropertyFilter("!sharedTo.name");
     104    Restriction sharedTo = null;
     105    if (sharedToFilter != null) sharedTo = sharedToFilter.getRestriction(dc, null);
    101106    items = project.getItems(itemTypes,
    102107      cc.getPage() * cc.getRowsPerPage(), cc.getRowsPerPage(), cc.getItemPermission(),
    103       cc.getInclude());
     108      cc.getInclude(), sharedTo);
    104109  }
    105110  catch (Throwable t)
     
    256261        title="Permission"
    257262      />
    258       <tbl:columndef 
     263      <tbl:columndef
    259264        id="sharedTo"
    260265        title="Shared to"
     266        filterable="true"
     267        filterproperty="!sharedTo.name"
     268        datatype="string"
    261269      />
    262270      <tbl:toolbar>
  • trunk/www/views/items/list_items.jsp

    r4887 r5167  
    4040  import="net.sf.basedb.core.Directory"
    4141  import="net.sf.basedb.core.Metadata"
     42  import="net.sf.basedb.core.PropertyFilter"
    4243  import="net.sf.basedb.core.query.ResultList"
     44  import="net.sf.basedb.core.query.Restriction"
    4345  import="net.sf.basedb.util.Enumeration"
    4446  import="net.sf.basedb.util.ShareableUtil"
     
    8587  {
    8688    String filterItem = cc.getPropertyValue("type");
    87     Set<Item> itemTypes = null; 
     89    Set<Item> itemTypes = null;
    8890    if (filterItem != null)
    8991    {
     
    9496      }
    9597    }
     98    PropertyFilter sharedToFilter = cc.getPropertyFilter("!sharedTo.name");
     99    Restriction sharedTo = null;
     100    if (sharedToFilter != null)
     101    {
     102      sharedTo = sharedToFilter.getRestriction(dc, null);
     103      // If we filter on "Shared to" we must make sure to only
     104      // include Shareable items in the query
     105      if (itemTypes != null)
     106      {
     107        itemTypes.retainAll(Metadata.getShareableItems());
     108      }
     109      else
     110      {
     111        itemTypes = Metadata.getShareableItems();
     112      }
     113    }
    96114    User loggedInUser = User.getById(dc, sc.getLoggedInUserId());
    97     allItems = loggedInUser.getItems(itemTypes, cc.getPage() * cc.getRowsPerPage(), cc.getRowsPerPage(), null);
     115    if (itemTypes == null || itemTypes.size() > 0)
     116    {
     117      allItems = loggedInUser.getItems(itemTypes, cc.getPage() * cc.getRowsPerPage(),
     118          cc.getRowsPerPage(), null, sharedTo);
     119    }
    98120    totalCount = allItems.getTotalCount();
    99121  }
     
    228250        title="Description"
    229251      />
    230       <tbl:columndef
    231         id="sharedTo"
    232         title="Shared to"
     252      <tbl:columndef
     253        id="sharedTo"
     254        title="Shared to"
     255        filterable="true"
     256        filterproperty="!sharedTo.name"
     257        datatype="string"
    233258      />
    234259      <tbl:toolbar>
Note: See TracChangeset for help on using the changeset viewer.