Changeset 7770


Ignore:
Timestamp:
Feb 10, 2020, 1:53:05 PM (22 months ago)
Author:
Nicklas Nordborg
Message:

References #2202: Include information from parent items in list pages

Implemented support for filtering on parent item columns. Basically this works by executing an extra query just to find the matching parent items for each of the columns and then using the "Item list" functionality to traverse down to find the child items.

This can take a long time if there are many steps between the parent and child levels. To improve performance a simple cache has been implemented.

The filtering feature is also limiting the parent items that are supported to those that can be used for items lists. There is also one remaining issue with subtypes that has the "Push annotations to parent" flag set. When displaying data, those items will be found since the annotation system in BASE knows that it should go back down in those branches, but the item list functionality doesn't. Thus, filtering on such items will never return any results.

Location:
trunk/src
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/list/ParentItemAnnotationColumn.java

    r7768 r7770  
    11package net.sf.basedb.clients.web.extensions.list;
    22
     3import java.util.List;
    34import java.util.Set;
    45import java.util.TreeSet;
    56
     7import net.sf.basedb.clients.web.util.HTML;
    68import net.sf.basedb.core.Annotatable;
    79import net.sf.basedb.core.AnnotationType;
    810import net.sf.basedb.core.snapshot.AnnotationSnapshot;
    911import net.sf.basedb.core.snapshot.AnnotationTypeFilter;
     12import net.sf.basedb.util.Enumeration;
    1013import net.sf.basedb.util.filter.Filter;
    1114
     
    2730    this.at = at;
    2831    this.atFilter = new AnnotationTypeFilter(at);
     32    if (at.isEnumeration())
     33    {
     34      Enumeration<String, String> annotationEnum = new Enumeration<String, String>();
     35      annotationEnum.add("", "-none-");
     36      List<?> values = at.getValues();
     37      for (Object value : values)
     38      {
     39        String encoded = HTML.encodeTags(value.toString());
     40        annotationEnum.add(encoded, encoded);
     41      }
     42      setEnumeration(annotationEnum);
     43    }
    2944  }
    3045 
  • trunk/src/clients/web/net/sf/basedb/clients/web/extensions/list/ParentItemColumn.java

    r7768 r7770  
    1111import net.sf.basedb.core.ItemSubtype;
    1212import net.sf.basedb.core.Metadata;
     13import net.sf.basedb.core.Type;
    1314import net.sf.basedb.core.Metadata.PropertyPath;
    1415import net.sf.basedb.util.AnnotationUtil;
     
    7475          col.setTitle(subtype.getName());
    7576          col.setTooltip(subtype.getName());
     77          col.setFilterProperty("/"+tmp[1]+"/"+tmp[2]+"/name");
    7678        }
     79        col.setValueType(Type.STRING);
    7780        if (property == null || property.getHibernateType().isEntityType())
    7881        {
     
    105108    setProperty(id);
    106109    setExportable(true);
     110    setFilterable(true);
    107111  }
    108112
  • trunk/src/core/net/sf/basedb/core/ItemContext.java

    r7703 r7770  
    2727import net.sf.basedb.core.query.Expressions;
    2828import net.sf.basedb.core.query.Hql;
     29import net.sf.basedb.core.query.IdListRestriction;
    2930import net.sf.basedb.core.query.Orders;
    3031import net.sf.basedb.core.query.Order;
     
    15161517  // Do not auto-join queries containing filter properties with the following prefixes
    15171518  private static final Set<String> NO_AUTO_JOIN_PREFIXES = new HashSet<String>(
    1518     Arrays.asList("£", "&", "!", "¤", "|"));
     1519    Arrays.asList("£", "&", "!", "¤", "|", "/"));
    15191520 
    15201521  /**
     
    16821683    {
    16831684      Map<Integer, List<Restriction>> allRestrictions = new HashMap<Integer, List<Restriction>>();
     1685      Map<Integer, IdListRestriction> rowIdListRestriction = new HashMap<Integer, IdListRestriction>();
    16841686      for (PropertyFilterPair filterPair : propertyFilters.values())
    16851687      {
     
    16901692          {
    16911693            Restriction r = filter.getRestriction(dc, query);
     1694            int rowIndex = filter.getRowIndex();
     1695            if (r instanceof IdListRestriction)
     1696            {
     1697              // Filters that result in a "IdListRestriction" are merged to a single id-list
     1698              // since that typically will result in a shorter list in the final SQL
     1699              IdListRestriction rowIdR = rowIdListRestriction.get(rowIndex);
     1700              if (rowIdR == null)
     1701              {
     1702                rowIdListRestriction.put(rowIndex, (IdListRestriction)r);
     1703              }
     1704              else
     1705              {
     1706                rowIdR.intersect((IdListRestriction)r);
     1707                r = null;
     1708              }
     1709            }
    16921710            if (r != null)
    16931711            {
    1694               int rowIndex = filter.getRowIndex();
    16951712              List<Restriction> rowRestrictions = allRestrictions.get(rowIndex);
    16961713              if (rowRestrictions == null)
  • trunk/src/core/net/sf/basedb/core/PropertyFilter.java

    r7642 r7770  
    2828import java.util.Collections;
    2929import java.util.List;
     30import java.util.Set;
     31import java.util.SortedSet;
     32import java.util.TreeSet;
    3033import java.util.regex.Matcher;
    3134import java.util.regex.Pattern;
    3235
     36import net.sf.basedb.core.SyncFilter.SourceItemTransform;
    3337import net.sf.basedb.core.data.PropertyFilterData;
    3438import net.sf.basedb.core.data.ReporterData;
     
    4549import net.sf.basedb.core.query.Dynamic;
    4650import net.sf.basedb.core.query.Hql;
     51import net.sf.basedb.core.query.IdListRestriction;
     52import net.sf.basedb.util.listable.ListableUtil;
     53import net.sf.basedb.util.listable.SourceItemTransformerFactory;
     54import net.sf.basedb.util.listable.SourceItemTransformerWithCache;
     55import net.sf.basedb.util.listable.TransformContext;
    4756import net.sf.basedb.util.units.UnitUtil;
    4857
     
    790799      }
    791800    }
    792    
     801    else if (property != null && property.startsWith("/"))
     802    {
     803      // Property is Parent-item filter: /TYPE/subtype-id/(property|#annotation-id)
     804      String[] parts = property.split("/", 4);
     805      Item parentType = Item.valueOf(parts[1]);
     806      ItemSubtype subtype = ItemSubtype.getById(dc, (Integer)Type.INT.parseString(parts[2]));
     807      String parentProperty = parts[3];
     808     
     809      // We execute a query for the parent items...
     810      EntityQuery subquery = new AbstractEntityQuery(parentType, parentType, null, "id", false, null)
     811      {};
     812      subquery.restrict(Restrictions.eq(Hql.property("itemSubtype"), Hql.entity(subtype)));
     813      PropertyFilter pp = new PropertyFilter(parentProperty, operator, getValue(), getValueType());
     814      subquery.restrict(pp.getRestriction(dc, subquery));
     815
     816      // We then transform the list if ID:s to a list of child item ID:s using ItemList functionality
     817      SortedSet<Integer> parentIds = new TreeSet<>(subquery.idList(dc));
     818      TransformContext tCtx = new TransformContext(dc);
     819
     820      SourceItemTransformerFactory factory = ListableUtil.getTransformerFactory(query.getItemType());
     821      factory = new SourceItemTransformerWithCache(factory);
     822      Set<Integer> myIds = factory.create(parentType, SourceItemTransform.PARENT_TO_CHILD).transform(tCtx, parentIds);
     823     
     824      // The final ID list is returned as a restriction
     825      restriction = new IdListRestriction(myIds);
     826    }
    793827    else
    794828    {
  • trunk/src/core/net/sf/basedb/core/SyncFilter.java

    r6927 r7770  
    472472    should produce the same MD5.
    473473  */
    474   static String toMd5(SortedSet<Integer> listOfIds)
     474  public static String toMd5(SortedSet<Integer> listOfIds)
    475475  {
    476476    MessageDigest md5 = MD5.newInstance();
  • trunk/src/core/net/sf/basedb/util/listable/TransformContext.java

    r6848 r7770  
    7272  }
    7373 
     74  /**
     75    Get a cache that can be used for storing transformation
     76    results for some time. The cache is stored in the current
     77    session and is lost if the user logs out.
     78    @since 3.16
     79  */
     80  public TransformCache getCache()
     81  {
     82    TransformCache cache = dc.getSessionControl().getSessionSetting(TransformCache.class.getName());
     83    if (cache == null)
     84    {
     85      cache = new TransformCache(20);
     86      dc.getSessionControl().setSessionSetting(TransformCache.class.getName(), cache);
     87    }
     88    return cache;
     89  }
     90
    7491}
Note: See TracChangeset for help on using the changeset viewer.