Changeset 4723


Ignore:
Timestamp:
Jan 13, 2009, 9:20:26 AM (13 years ago)
Author:
Nicklas Nordborg
Message:

References #1190: API and interface for creating biomaterial lists

All functionality should now be in place. It turned out that the one-step-down restriction wasn't neccesary since it was possible to link multiple steps together. In other words, it is now possible to generate a list with all labeled extracts that descend from the selected biosources. It also possible to move in the other direction, eg. from labeled extract to biosource.

Location:
trunk
Files:
7 added
8 edited

Legend:

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

    r4712 r4723  
    3737import net.sf.basedb.core.data.BioMaterialData;
    3838import net.sf.basedb.core.data.BioMaterialListData;
     39import net.sf.basedb.util.biomaterial.ListUtil;
    3940
    4041/**
     
    401402    member type of the list.
    402403    @return An {@link ItemQuery} object
    403     @throws BaseException If the query could not be created and configured.
     404    @throws BaseException If the query could not be created and configured
     405    @see ListUtil#getQuery(Item)
    404406  */
    405407  public ItemQuery<? extends BioMaterial> getAllBioMaterials()
    406408    throws BaseException
    407409  {
    408     ItemQuery<? extends BioMaterial> query;
    409     Item memberType = getMemberType();
    410     if (memberType == Item.BIOSOURCE)
    411     {
    412       query = BioSource.getQuery();
    413     }
    414     else if (memberType == Item.SAMPLE)
    415     {
    416       query = Sample.getQuery();
    417     }
    418     else if (memberType == Item.EXTRACT)
    419     {
    420       query = Extract.getQuery();
    421     }
    422     else if (memberType == Item.LABELEDEXTRACT)
    423     {
    424       query = LabeledExtract.getQuery();
    425     }
    426     else
    427     {
    428       throw new AssertionError("Unsupported member type in list '" +
    429           getName() + "': " + memberType);
    430     }
    431     return query;
     410    return ListUtil.getQuery(getMemberType());
    432411  }
    433412
  • trunk/src/core/net/sf/basedb/util/biomaterial/BioSourceToSampleTransformer.java

    r4712 r4723  
    2323
    2424import java.util.Collection;
     25import java.util.HashSet;
     26import java.util.Set;
    2527
    2628import net.sf.basedb.core.BioSource;
     
    2931import net.sf.basedb.core.ItemQuery;
    3032import net.sf.basedb.core.Sample;
     33import net.sf.basedb.core.Type;
    3134import net.sf.basedb.core.query.Expressions;
    3235import net.sf.basedb.core.query.Hql;
    3336import net.sf.basedb.core.query.Restrictions;
     37import net.sf.basedb.util.collections.BasicItemToIdTransformer;
    3438import net.sf.basedb.util.collections.CollectionTransformer;
    3539
     
    6569      Collection<? super Sample> samples)
    6670  {
    67     ItemQuery<Sample> query = Sample.getQuery();
    68     query.include(Include.ALL);
     71    // Copy source ID:s so we can use them as a parameter in the query
     72    Set<Integer> sourceIds = new HashSet<Integer>();
     73    BasicItemToIdTransformer idTransformer = new BasicItemToIdTransformer();
     74    idTransformer.transform(bioSources, sourceIds);
     75
     76    ItemQuery<Sample> query = createQuery();
    6977    query.restrict(
    7078      Restrictions.in(
     
    7381      )
    7482    );
    75     query.setParameter("biosources", bioSources, null);
     83    query.setParameter("biosources", sourceIds, Type.INT);
    7684    int size = samples.size();
    7785    samples.addAll(query.list(dc));
    7886    return samples.size() - size;
    7987  }
     88  // -------------------------------------------------
     89 
     90  /**
     91    Create a query for loading samples. The default implemenation will
     92    simply load all samples. The restriction needed to locate the biosources
     93    that are parents is automatically applied by the <code>transform</code>
     94    method. Subclasses may override this method to create an alternate query
     95    (for example, with more filters).
     96    @return A query object
     97  */
     98  protected ItemQuery<Sample> createQuery()
     99  {
     100    ItemQuery<Sample> query = Sample.getQuery();
     101    query.include(Include.ALL);
     102    return query;
     103  }
    80104 
    81105}
  • trunk/src/core/net/sf/basedb/util/biomaterial/ListUtil.java

    r4712 r4723  
    2222package net.sf.basedb.util.biomaterial;
    2323
     24import java.util.ArrayList;
     25import java.util.Arrays;
    2426import java.util.Collection;
    2527import java.util.HashSet;
    26 import java.util.Set;
    27 
     28import java.util.Iterator;
     29import java.util.List;
     30
     31import net.sf.basedb.core.BaseException;
    2832import net.sf.basedb.core.BioMaterial;
    2933import net.sf.basedb.core.BioMaterialList;
     34import net.sf.basedb.core.BioSource;
     35import net.sf.basedb.core.DbControl;
     36import net.sf.basedb.core.Extract;
    3037import net.sf.basedb.core.InvalidDataException;
     38import net.sf.basedb.core.Item;
     39import net.sf.basedb.core.ItemQuery;
     40import net.sf.basedb.core.LabeledExtract;
    3141import net.sf.basedb.core.PermissionDeniedException;
     42import net.sf.basedb.core.Sample;
     43import net.sf.basedb.util.collections.AddAllTransformer;
    3244import net.sf.basedb.util.collections.CollectionTransformer;
     45import net.sf.basedb.util.collections.MultiStepCollectionTransformer;
    3346
    3447/**
     
    4356
    4457  /**
     58    Get a query that returns all biomaterials that can possibly be
     59    members of this list. NOTE! This is just a convenience function
     60    that calls {@link BioSource#getQuery()}, etc. depending on the
     61    member type of the list.
     62    @return An {@link ItemQuery} object
     63    @throws BaseException If the query could not be created and configured.
     64  */
     65  public static ItemQuery<? extends BioMaterial> getQuery(Item biomaterialType)
     66    throws BaseException
     67  {
     68    ItemQuery<? extends BioMaterial> query;
     69    if (biomaterialType == Item.BIOSOURCE)
     70    {
     71      query = BioSource.getQuery();
     72    }
     73    else if (biomaterialType == Item.SAMPLE)
     74    {
     75      query = Sample.getQuery();
     76    }
     77    else if (biomaterialType == Item.EXTRACT)
     78    {
     79      query = Extract.getQuery();
     80    }
     81    else if (biomaterialType == Item.LABELEDEXTRACT)
     82    {
     83      query = LabeledExtract.getQuery();
     84    }
     85    else
     86    {
     87      throw new AssertionError("Can't create query for item type: " +
     88          biomaterialType);
     89    }
     90    return query;
     91  }
     92 
     93 
     94  /**
    4595    Adds items to a biomaterial list. The source collection can optionally
    46     be transformed by a transformer. If not transformer is given, the
     96    be transformed by a transformer. If no transformer is given, the
    4797    source collection is added. The items added to the list must of course
    4898    be of the correct {@link BioMaterialList#getMemberType()} for the list.
    4999   
    50100    @param list The list to add items to
    51     @param source The source collection of biomaterials
     101    @param sources The source collection of biomaterials
    52102    @param transformer An optional transformer
    53103    @return The number of items added to the biomaterial list
     
    58108  */
    59109  public static <S extends BioMaterial> int addToList(BioMaterialList list,
    60     Collection<? extends S> source,
     110    Collection<? extends S> sources,
    61111    CollectionTransformer<S, ? extends BioMaterial> transformer)
    62112    throws InvalidDataException, PermissionDeniedException
    63113  {
    64     Set<BioMaterial> toAdd = new HashSet<BioMaterial>();
    65     if (transformer == null)
    66     {
    67       toAdd.addAll(source);
     114    Iterator<? extends BioMaterial> iterator = null;
     115    if (transformer != null)
     116    {
     117      Collection<BioMaterial> transformed = new HashSet<BioMaterial>();
     118      transformer.transform(sources, transformed);
     119      iterator = transformed.iterator();
    68120    }
    69121    else
    70122    {
    71       toAdd = new HashSet<BioMaterial>();
    72       transformer.transform(source, toAdd);
    73     }
    74     int added = list.add(toAdd.iterator());
     123      iterator = sources.iterator();
     124    }
     125    int added = list.add(iterator);
    75126    return added;
    76127  }
     128 
     129  /**
     130    Create a transformer that can transform a collection with
     131    <code>sourceItem</code>:s into a collection with <code>destinationItem</code>:s
     132    by following parent/child paths. Both the source and destination must be
     133    one of {@link Item#BIOSOURCE}, {@link Item#SAMPLE}, {@link Item#EXTRACT}
     134    or {@link Item#LABELEDEXTRACT}.
     135   
     136    @param dc The DbControl the transformers should use for loading
     137      items from the database
     138    @param sourceItem The type of source items
     139    @param destinationItem The type of destination items
     140    @param pooled If pooled children/parents should be considered or not
     141    @return A collection transformer (never null)
     142  */
     143  @SuppressWarnings("unchecked")
     144  public static CollectionTransformer createTransformer(DbControl dc, Item sourceItem, Item destinationItem, boolean pooled)
     145  {
     146    // The allowed item types
     147    final List<Item> INDEX = Arrays.asList(new Item[] { Item.BIOSOURCE, Item.SAMPLE, Item.EXTRACT, Item.LABELEDEXTRACT });
     148    int dIndex = INDEX.indexOf(destinationItem);
     149    if (dIndex == -1)
     150    {
     151      throw new InvalidDataException("Destination item type must be a biomaterial: " +
     152          destinationItem);
     153    }
     154    int sIndex = INDEX.indexOf(sourceItem);
     155    if (dIndex == -1)
     156    {
     157      throw new InvalidDataException("Source item type must be a biomaterial: " +
     158          destinationItem);
     159    }
     160    int step = sIndex < dIndex ? 1 : -1;
     161   
     162    List<CollectionTransformer> transformers = new ArrayList<CollectionTransformer>();
     163    while (sIndex != dIndex)
     164    {
     165      if (sourceItem == Item.BIOSOURCE)
     166      {
     167        // Moving down
     168        transformers.add(new BioSourceToSampleTransformer(dc));
     169      }
     170      else if (sourceItem == Item.SAMPLE)
     171      {
     172        if (step == 1)
     173        {
     174          // Moving down
     175          if (pooled) transformers.add(new PooledChildrenTransformer<Sample>(dc, true, Sample.getQuery()));
     176          transformers.add(new SampleToExtractTransformer(dc));
     177        }
     178        else
     179        {
     180          // Moving up
     181          if (pooled) transformers.add(new PooledParentsTransformer<Sample>(dc, true, Sample.getQuery()));
     182          transformers.add(new SampleToBioSourceTransformer(dc));
     183        }
     184      }
     185      else if (sourceItem == Item.EXTRACT)
     186      {
     187        if (step == 1)
     188        {
     189          // Moving down
     190          if (pooled) transformers.add(new PooledChildrenTransformer<Extract>(dc, true, Extract.getQuery()));
     191          transformers.add(new ExtractToLabeledExtractTransformer(dc));
     192        }
     193        else
     194        {
     195          // Moving up
     196          if (pooled) transformers.add(new PooledParentsTransformer<Extract>(dc, true, Extract.getQuery()));
     197          transformers.add(new ExtractToSampleTransformer(dc));
     198        }
     199      }
     200      else if (sourceItem == Item.LABELEDEXTRACT)
     201      {
     202        // Moving up
     203        if (pooled) transformers.add(new PooledParentsTransformer<LabeledExtract>(dc, true, LabeledExtract.getQuery()));
     204        transformers.add(new LabeledExtractToExtractTransformer(dc));
     205      }
     206      sIndex += step;
     207      sourceItem = INDEX.get(sIndex);
     208    }
     209   
     210    if (transformers.size() == 0)
     211    {
     212      // When sourceItem == destinationItem to begin with
     213      transformers.add(new AddAllTransformer());
     214    }
     215   
     216    if (pooled && destinationItem != Item.BIOSOURCE)
     217    {
     218      if (step == 1)
     219      {
     220        // Moving down
     221        transformers.add(new PooledChildrenTransformer(dc, true, getQuery(destinationItem)));
     222      }
     223      else
     224      {
     225        // Moving up
     226        transformers.add(new PooledParentsTransformer(dc, true, getQuery(destinationItem)));
     227      }
     228    }
     229   
     230    CollectionTransformer ct = null;
     231    if (transformers.size() == 1)
     232    {
     233      ct = transformers.get(0);
     234    }
     235    else
     236    {
     237      ct = new MultiStepCollectionTransformer(transformers);
     238    }
     239    return ct;
     240  }
     241 
    77242}
  • trunk/src/core/net/sf/basedb/util/biomaterial/PooledChildrenTransformer.java

    r4712 r4723  
    5252  private final DbControl dc;
    5353  private final ItemQuery<I> query;
    54   public PooledChildrenTransformer(DbControl dc, ItemQuery<I> query)
     54  private final boolean copySources;
     55 
     56  public PooledChildrenTransformer(DbControl dc, boolean copySources, ItemQuery<I> query)
    5557  {
    5658    this.dc = dc;
     59    this.copySources = copySources;
    5760    this.query = query;
    5861    query.include(Include.ALL);
     
    8487    int originalSize = destination.size();
    8588   
     89    // Copy source biomaterials
     90    if (copySources) destination.addAll(source);
     91   
    8692    // We need to loop so we can move down as many levels as we need
    8793    while (sourceIds.size() > 0)
     
    98104    return destination.size() - originalSize;
    99105  }
     106  // --------------------------------------------------
    100107
    101108}
  • trunk/src/core/net/sf/basedb/util/collections/CollectionTransformer.java

    r4712 r4723  
    3131  should NOT use the same collection as both source and destination since that
    3232  may interfere with iterators on the source collection.
    33   The destinatio collection may contain elements of the same or a different type
     33  The destination collection may contain elements of the same or a different type
    3434  as the source collection.
    3535
     
    5151      This value may have a different meaning depending on the implementor. For
    5252      example, some implementor may add elements while other implementor may
    53       remove elements. A return value of 0, indicates that no modifications at all
     53      remove elements. A return value of 0 should always indicate that no modifications
    5454      has been made to the destination collection.
    5555  */
  • trunk/src/test/TestSample.java

    r4712 r4723  
    446446      dc = TestUtil.getDbControl();
    447447      Sample s = Sample.getById(dc, sampleId);
    448       PooledChildrenTransformer<Sample> pct = new PooledChildrenTransformer<Sample>(dc, Sample.getQuery());
     448      PooledChildrenTransformer<Sample> pct = new PooledChildrenTransformer<Sample>(dc, false, Sample.getQuery());
    449449      List<Sample> children = new ArrayList<Sample>();
    450450      int numAdded = pct.transform(Collections.singleton(s), children);
  • trunk/www/biomaterials/lists/edit_list.jsp

    r4712 r4723  
    5454  int numSelectedLists = cc.getSelected().size();
    5555  String formId = request.getParameter("formId");
    56   String fromContext = Values.getString(request.getParameter("fromContext"));
     56  String fromContext = Values.getStringOrNull(request.getParameter("fromContext"));
    5757  String subContext = request.getParameter("subContext");
    5858
     
    6262    cc.removeObject("item");
    6363    addBioMaterials = Values.getBoolean(request.getParameter("addBioMaterials"));
    64     memberType = fromContext != null ? Item.valueOf(fromContext) : Item.fromValue(Values.getInt(cc.getPropertyValue("memberType")));
     64    if (numSelectedLists > 0)
     65    {
     66      for (int selectedId : cc.getSelected())
     67      {
     68        BioMaterialList selectedList = BioMaterialList.getById(dc, selectedId);
     69        if (memberType == null)
     70        {
     71          memberType = selectedList.getMemberType();
     72        }
     73        else if (memberType != selectedList.getMemberType())
     74        {
     75          numSelectedLists = 0;
     76          memberType = null;
     77          break;
     78        }
     79      }
     80    }
     81    if (memberType == null)
     82    {
     83      memberType = fromContext != null ? Item.valueOf(fromContext) : Item.fromValue(Values.getInt(cc.getPropertyValue("memberType")));
     84    }
    6585    mergeLists = numSelectedLists > 0;
    6686  }
     
    138158      Forms.checkRadio(radio, name);
    139159    }
    140     function setAddToList(memberType, selectedOption)
    141     {
    142       var frm = document.forms['list'];
    143       if (memberType)
    144       {
    145         Forms.selectListOption(frm.memberType, memberType);
    146       }
    147       if (selectedOption)
    148       {
    149         Forms.checkRadio(frm.add, selectedOption);
    150       }
    151     }
     160
    152161    // Get the ID:s of all selected items
    153162    var selectedItems = new Array();
     
    199208        <td class="prompt">Member type</td>
    200209        <td>
    201           <select name="memberType" <%=fromContext != null ? "disabled" : ""%>>
     210          <select name="memberType" <%=mergeLists ? "disabled" : "" %>>
    202211            <option value="BIOSOURCE" <%=memberType == Item.BIOSOURCE ? "selected" : ""%>>Biosource
    203212            <option value="SAMPLE" <%=memberType == Item.SAMPLE ? "selected" : ""%>>Sample
     
    210219      if (addBioMaterials)
    211220      {
    212         boolean hasSourceOption = true;
    213         boolean hasPooledOption = true;
    214         boolean hasChildOption = true;
    215         Item childType = null;
    216         if (memberType == Item.BIOSOURCE)
    217         {
    218           hasPooledOption = false;
    219           childType = Item.SAMPLE;
    220         }
    221         else if (memberType == Item.SAMPLE)
    222         {
    223           childType = Item.EXTRACT;
    224         }
    225         else if (memberType == Item.EXTRACT)
    226         {
    227           childType = Item.LABELEDEXTRACT;
    228         }
    229         else if (memberType == Item.LABELEDEXTRACT)
    230         {
    231           hasChildOption = false;
    232         }
    233221        %>
    234222        <tr valign="top">
     
    248236        </tr>
    249237        <tr>
    250           <td class="prompt">Add to list</td>
     238          <td class="prompt">Include pooled</td>
    251239          <td>
    252             <%
    253             if (hasSourceOption)
    254             {
    255               %>
    256               <input type="radio" name="add" value="source" checked
    257                 onchange="setAddToList('<%=memberType.name()%>')"><a
    258                 href="javascript:setAddToList('<%=memberType.name()%>', 'source');"
    259                 >Source items only</a><br>
    260               <%
    261             }
    262             if (hasPooledOption)
    263             {
    264               %>
    265               <input type="radio" name="add" value="pooled"
    266                 onchange="setAddToList('<%=memberType.name()%>')"><a
    267                 href="javascript:setAddToList('<%=memberType.name()%>', 'pooled');"
    268                 >Source items + pooled children of same type (<%=memberType%>)</a><br>
    269               <%
    270             }
    271             if (hasChildOption)
    272             {
    273               %>
    274               <input type="radio" name="add" value="children"
    275                 onchange="setAddToList('<%=childType.name()%>')"><a
    276                 href="javascript:setAddToList('<%=childType.name()%>', 'children');"
    277                 >Children of next type (<%=childType%>)</a><br>
    278               <% 
    279             }
    280             %>
     240            <input type="checkbox" name="pooled" value="1" ><a
     241                href="javascript:Forms.toggleCheckbox(document.forms['list'].pooled);"
     242                >Include pooled children/parents in the list</a><br>
    281243          </td>
    282244        </tr>
  • trunk/www/biomaterials/lists/index.jsp

    r4712 r4723  
    4747  import="net.sf.basedb.util.OwnableUtil"
    4848  import="net.sf.basedb.util.biomaterial.BioSourceToSampleTransformer"
     49  import="net.sf.basedb.util.biomaterial.SampleToExtractTransformer"
     50  import="net.sf.basedb.util.biomaterial.ExtractToLabeledExtractTransformer"
    4951  import="net.sf.basedb.util.biomaterial.PooledChildrenTransformer"
    5052  import="net.sf.basedb.util.collections.CollectionTransformer"
     
    151153        Item fromContext = Item.valueOf(request.getParameter("fromContext"));
    152154        String subContext = Values.getString(request.getParameter("subContext"), "");
     155        boolean pooled = Values.getBoolean(request.getParameter("pooled"));
     156       
    153157        ItemQuery<? extends BioMaterial> query =
    154158          (ItemQuery<? extends BioMaterial>)sc.getCurrentContext(fromContext, subContext).getQuery();
     
    172176        }
    173177        // else -- no modifications to the query mean that we only get the current page
     178       
     179        // This is our list of source items (eg. the selected items in the list)
    174180        List<? extends BioMaterial> sources = query.list(dc);
    175         CollectionTransformer transformer = null;
    176         if ("source".equals(add))
    177         {
    178           // No transformer needed
    179         }
    180         else if ("pooled".equals(add))
    181         {
    182           ListUtil.addToList(list, sources, null);
    183           ItemQuery<? extends BioMaterial> pooledQuery = list.getAllBioMaterials();
    184           transformer = new PooledChildrenTransformer(dc, pooledQuery);
    185         }
    186         else if ("children".equals(add))
    187         {
    188           if (memberType == Item.SAMPLE)
    189           {
    190             transformer = new BioSourceToSampleTransformer(dc);
    191           }
    192           // TODO -- other biomaterial types
    193         }
    194         ListUtil.addToList(list, sources, transformer);
     181        // Create a transformer that takes the source list and finds related
     182        // items
     183        CollectionTransformer transformer =
     184          ListUtil.createTransformer(dc, fromContext, memberType, pooled);
     185        int numAdded = ListUtil.addToList(list, sources, transformer);
    195186      }
    196187     
Note: See TracChangeset for help on using the changeset viewer.