Changeset 6022


Ignore:
Timestamp:
Mar 22, 2012, 3:01:20 PM (11 years ago)
Author:
Nicklas Nordborg
Message:

Fixes #1672: Join annotation values into a main item query

There is now support for this in the Query API. The main entry point is the Annotations.expression(), Annotations.innerJoin() and Annotations.leftJoin() methods. The implementation is in the AnnotationJoin and AnnotationExpression classes. The expression variant uses an auto-joiner to automatically create the correct join. Otherwise, an explict join can be use together with a regular Hql.alias() expression.

In the data layer, the functionality is provided by the shortcut link defined by AnnotatableData.getAnnotations(). The AnnotationLink provides the mappings that are needed to reach the final ***Values table. To get XDoclet to create the mapping that we needed we have added support for property-ref and mutable.

Location:
trunk
Files:
5 added
12 edited

Legend:

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

    r5319 r6022  
    331331  {
    332332    addAutoJoiner(HqlQueryJoiners.getReporterListJoiner(joinType));
     333    addAutoJoiner(HqlQueryJoiners.getAnnotationJoiner(joinType));
    333334  }
    334335 
  • trunk/src/core/net/sf/basedb/core/HqlQueryJoiners.java

    r4517 r6022  
    2222package net.sf.basedb.core;
    2323
     24import net.sf.basedb.core.query.AnnotationExpression;
     25import net.sf.basedb.core.query.Annotations;
    2426import net.sf.basedb.core.query.AutoJoiner;
    2527import net.sf.basedb.core.query.Expressions;
     
    6668  {
    6769    return joinType == JoinType.LEFT ? REPORTER_LIST_LEFT : REPORTER_LIST_INNER;
     70  }
     71 
     72  public static AnnotationJoiner getAnnotationJoiner(JoinType joinType)
     73  {
     74    return new AnnotationJoiner(joinType);
    6875  }
    6976
     
    118125    // -------------------------------------------
    119126  }
     127 
     128  /**
     129    Joiner for annotations.
     130    @since 3.2
     131  */
     132  private static class AnnotationJoiner
     133    implements AutoJoiner<HqlQuery, AnnotationExpression>
     134  {
     135    private final JoinType joinType;
     136   
     137    private AnnotationJoiner(JoinType joinType)
     138    {
     139      this.joinType = joinType;
     140    }
     141   
     142    /*
     143      From the AutoJoiner interface
     144      -------------------------------------------
     145    */
     146    @Override
     147    public Class<HqlQuery> getQueryClass()
     148    {
     149      return HqlQuery.class;
     150    }
     151    @Override
     152    public Class<AnnotationExpression> getElementClass()
     153    {
     154      return AnnotationExpression.class;
     155    }
     156    @Override
     157    public void joinIfNeeded(HqlQuery query, AnnotationExpression element)
     158    {
     159      if (joinType == JoinType.LEFT)
     160      {
     161        query.join(Annotations.leftJoin(element.getAlias(), element.getAnnotationType(), element.getJoinAlias()));
     162      }
     163      else
     164      {
     165        query.join(Annotations.innerJoin(element.getAlias(), element.getAnnotationType(), element.getJoinAlias()));
     166      }
     167    }
     168    // -------------------------------------------
     169   
     170  }
    120171
    121172}
  • trunk/src/core/net/sf/basedb/core/StringUtil.java

    r5534 r6022  
    280280  }
    281281 
     282  /**
     283    Decapitalize the string by making sure the first character is lower-case. All
     284    other characters are left as they are. If the string is empty, the empty string
     285    is returned. If the string is null, null is returned.
     286    @since 3.2
     287  */
     288  public static final String decapitalize(String value)
     289  {
     290    if (value == null || value.length() == 0) return value;
     291    return value.substring(0, 1).toLowerCase() + value.substring(1);
     292  }
    282293}
  • trunk/src/core/net/sf/basedb/core/data/AnnotatableData.java

    r5818 r6022  
    2222*/
    2323package net.sf.basedb.core.data;
     24
     25import java.util.Set;
     26
     27import net.sf.basedb.core.data.annotations.AnnotationLink;
    2428
    2529/**
     
    7478  */
    7579  public void setAnnotationSet(AnnotationSetData annotationSet);
     80 
     81  /**
     82    Short-cut to all annotations belonging to this item. Used for HQL queries only.
     83    This is the inverse end.
     84   
     85    NOTE! The property-ref="annotationSet" require that AnnotationSetData
     86    implements Serializable
     87   
     88    @hibernate.set lazy="true" inverse="true" mutable="false"
     89    @hibernate.collection-key column="`annotationset_id`" property-ref="annotationSet"
     90    @hibernate.collection-one-to-many class="net.sf.basedb.core.data.annotations.AnnotationLink"
     91    @since 3.2
     92  */
     93  public Set<AnnotationLink> getAnnotations();
     94
     95 
    7696}
  • trunk/src/core/net/sf/basedb/core/data/AnnotatedData.java

    r5818 r6022  
    2222*/
    2323package net.sf.basedb.core.data;
     24
     25import java.util.Set;
     26
     27import net.sf.basedb.core.data.annotations.AnnotationLink;
    2428
    2529/**
     
    5559    this.annotationSet = annotationSet;
    5660  }
     61  @Override
     62  public Set<AnnotationLink> getAnnotations()
     63  {
     64    return null;
     65  }
     66  void setAnnotations(Set<AnnotationLink> links)
     67  {}
    5768  // -------------------------------------------
    58 
     69 
    5970}
  • trunk/src/core/net/sf/basedb/core/data/AnnotationSetData.java

    r5818 r6022  
    2323package net.sf.basedb.core.data;
    2424
     25import java.io.Serializable;
    2526import java.util.Set;
    2627import java.util.HashSet;
     
    3940public class AnnotationSetData
    4041  extends BasicData
    41   implements LoggableData
     42  implements LoggableData, Serializable
    4243{
     44
     45  private static final long serialVersionUID = 7582258239220452911L;
     46
    4347  public AnnotationSetData()
    4448  {}
    4549
    46   private int itemType;
     50  private transient int itemType;
    4751  /**
    4852    Get the item type this annotation set is associated with.
     
    5862  }
    5963
    60   private Integer itemId;
     64  private transient Integer itemId;
    6165  /**
    6266    The ID if the item this annotation set is associated with. Can be null
     
    7579  }
    7680 
    77   private Map<AnnotationTypeData, AnnotationData> annotations;
     81  private transient Map<AnnotationTypeData, AnnotationData> annotations;
    7882  /**
    7983    The primary annotations in this annotation set. This is the inverse end.
     
    98102  }
    99103 
    100   private Set<AnnotationData> inherited;
     104  private transient Set<AnnotationData> inherited;
    101105  /**
    102106    Annotations that are inherited from other annotation sets.
     
    119123  }
    120124 
    121   private Set<AnnotationSetData> inheritedSets;
     125  private transient Set<AnnotationSetData> inheritedSets;
    122126  /**
    123127    Annotation sets from which this set should inherit all annotations.
     
    140144  }
    141145
    142   private Set<AnnotationSetData> inheritingSets;
     146  private transient Set<AnnotationSetData> inheritingSets;
    143147  /**
    144148    Annotation sets inherting annotations from this set.
  • trunk/src/core/net/sf/basedb/core/data/BioAssayData.java

    r5818 r6022  
    2525import java.util.Set;
    2626import java.util.HashSet;
     27
     28import net.sf.basedb.core.data.annotations.AnnotationLink;
    2729
    2830/**
     
    8890    this.annotationSet = annotationSet;
    8991  }
     92  @Override
     93  public Set<AnnotationLink> getAnnotations()
     94  {
     95    return null;
     96  }
     97  void setAnnotations(Set<AnnotationLink> annotations)
     98  {}
    9099  // -------------------------------------------
    91100
  • trunk/src/core/net/sf/basedb/core/data/BioAssaySetData.java

    r5818 r6022  
    2626import java.util.Map;
    2727import java.util.HashMap;
     28
     29import net.sf.basedb.core.data.annotations.AnnotationLink;
    2830
    2931/**
     
    103105    this.annotationSet = annotationSet;
    104106  }
     107  @Override
     108  public Set<AnnotationLink> getAnnotations()
     109  {
     110    return null;
     111  }
     112  void setAnnotations(Set<AnnotationLink> annotations)
     113  {}
    105114  // -------------------------------------------
    106115  /*
  • trunk/src/core/net/sf/basedb/core/data/PluginDefinitionData.java

    r5818 r6022  
    2323package net.sf.basedb.core.data;
    2424
     25import net.sf.basedb.core.data.annotations.AnnotationLink;
    2526import net.sf.basedb.core.plugin.About;
    2627
     
    7576    this.annotationSet = annotationSet;
    7677  }
     78  @Override
     79  public Set<AnnotationLink> getAnnotations()
     80  {
     81    return null;
     82  }
     83  void setAnnotations(Set<AnnotationLink> annotations)
     84  {}
    7785  // -------------------------------------------
    7886  /*
  • trunk/src/core/net/sf/basedb/core/data/WellData.java

    r5818 r6022  
    2222*/
    2323package net.sf.basedb.core.data;
     24
     25import java.util.Set;
     26
     27import net.sf.basedb.core.data.annotations.AnnotationLink;
    2428
    2529/**
     
    5458    this.annotationSet = annotationSet;
    5559  }
     60  @Override
     61  public Set<AnnotationLink> getAnnotations()
     62  {
     63    return null;
     64  }
     65  void setAnnotations(Set<AnnotationLink> annotations)
     66  {}
    5667  // -------------------------------------------
    5768 
  • trunk/src/core/net/sf/basedb/core/query/Annotations.java

    r6021 r6022  
    2424package net.sf.basedb.core.query;
    2525
     26import net.sf.basedb.core.InvalidUseOfNullException;
    2627import net.sf.basedb.core.Operator;
    2728import net.sf.basedb.core.AnnotationType;
     
    221222  }
    222223
     224  /**
     225    Create an expression representing the value of an annotation to the root item
     226    of the query. This method works best with single-valued annotation types. It
     227    can generate duplicate result rows for the same entity for multi-valued annotations.
     228    @param annotationType The annotation type to generate an expression for
     229    @return An expression
     230    @throws InvalidDataException If the annotationType is null
     231    @since 3.2
     232  */
     233  public static Expression expression(AnnotationType annotationType)
     234  {
     235    return expression(null, annotationType);
     236  }
     237 
     238  /**
     239    Create an expression representing the value of an annotation to a joined item
     240    of the query. This method works best with single-valued annotation types. It
     241    can generate duplicate result rows for the same entity for multi-valued annotations.
     242    @param alias The alias of a joined item or null to use the root item
     243    @param annotationType The annotation type to generate an expression for
     244    @return An expression
     245    @throws InvalidDataException If the annotationType is null
     246    @since 3.2
     247  */
     248  public static Expression expression(String alias, AnnotationType annotationType)
     249  {
     250    if (annotationType == null) throw new InvalidUseOfNullException("annotationType");
     251    return new AnnotationExpression(alias, annotationType);
     252  }
     253 
     254  /**
     255    Create an inner join between the root element of a query and
     256    the annotation values for the given annotation type.
     257   
     258    @param annotationType The annotation type to to join
     259    @param joinedAlias The alias to use for the joined annotation values
     260    @return A join query element
     261    @throws InvalidDataException If the annotationType or joinedAlias is null
     262    @since 3.2
     263  */
     264  public static Join innerJoin(AnnotationType annotationType, String joinedAlias)
     265  {
     266    return innerJoin(null, annotationType, joinedAlias);
     267  }
     268 
     269  /**
     270    Create an inner join between an already joined element of a query and
     271    the annotation values for the given annotation type.
     272   
     273    @param alias The alias of a joined item or null to use the root item
     274    @param annotationType The annotation type to to join
     275    @param joinedAlias The alias to use for the joined annotation values
     276    @return A join query element
     277    @throws InvalidDataException If the annotationType or joinedAlias is null
     278    @since 3.2
     279  */
     280  public static Join innerJoin(String alias, AnnotationType annotationType, String joinedAlias)
     281  {
     282    if (annotationType == null) throw new InvalidUseOfNullException("annotationType");
     283    if (joinedAlias == null) throw new InvalidUseOfNullException("joinedAlias");
     284    return new AnnotationJoin(JoinType.INNER, alias, annotationType, joinedAlias);
     285  }
     286 
     287  /**
     288    Create a left join between the root element of a query and
     289    the annotation values for the given annotation type.
     290   
     291    @param annotationType The annotation type to to join
     292    @param joinedAlias The alias to use for the joined annotation values
     293    @return A join query element
     294    @throws InvalidDataException If the annotationType or joinedAlias is null
     295    @since 3.2
     296  */
     297  public static Join leftJoin(AnnotationType annotationType)
     298  {
     299    return leftJoin(null, annotationType, null);
     300  }
     301 
     302  /**
     303    Create a left join between an already joined element of a query and
     304    the annotation values for the given annotation type.
     305   
     306    @param alias The alias of a joined item or null to use the root item
     307    @param annotationType The annotation type to to join
     308    @param joinedAlias The alias to use for the joined annotation values
     309    @return A join query element
     310    @throws InvalidDataException If the annotationType or joinedAlias is null
     311    @since 3.2
     312  */
     313  public static Join leftJoin(String alias, AnnotationType annotationType, String joinedAlias)
     314  {
     315    if (annotationType == null) throw new InvalidUseOfNullException("annotationType");
     316    return new AnnotationJoin(JoinType.LEFT, alias, annotationType, joinedAlias);
     317  }
     318 
    223319}
Note: See TracChangeset for help on using the changeset viewer.