Changeset 5879


Ignore:
Timestamp:
Nov 18, 2011, 3:02:31 PM (10 years ago)
Author:
Nicklas Nordborg
Message:

References #1616: Clone reporter information to per-experiment tables in the dynamic database

DynamicSpotQuery and DynamicPosQuery now join to the cloned reporter table if it exists and not told otherwise. It is possible to force the queries to use the master table if desired and also to use both.

The changes should automatically be used by any code that executes dynamic queries. In some cases this may be a problem if the calling code is not aware of that only a subset of all reporter properties may be available. The "Spot data" listing and "Expression builder" has been updated to only use the cloned reporter information.

Experiment explorer is more of a mess. The main problem is that the fixes for #1618 involved making some queries against the main reporter table without joins to the dynamic database. Now we'll need an alternate branch that do the same queries against the cloned reporter table if it exists. The difficult part is that the we need to support both variants and that the API used to get the information we need is not very similar...

Location:
trunk
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/clients/web/net/sf/basedb/clients/web/DynamicUtil.java

    r5440 r5879  
    2424
    2525import net.sf.basedb.core.BioAssaySet;
     26import net.sf.basedb.core.ClonedProperty;
    2627import net.sf.basedb.core.ExtendedProperties;
    2728import net.sf.basedb.core.ExtendedProperty;
     
    3637import net.sf.basedb.core.RawDataProperty;
    3738import net.sf.basedb.core.RawDataType;
     39import net.sf.basedb.core.ReporterCloneTemplate;
    3840import net.sf.basedb.core.SessionControl;
    3941import net.sf.basedb.core.Type;
     
    171173  }
    172174 
     175  public static void addReporterColumns(List<TableColumn> columns, DbControl dc, ReporterCloneTemplate template,
     176      String idPrefix, String propertyPrefix, String titlePrefix)
     177  {
     178    if (template == null)
     179    {
     180      addReporterColumns(columns, dc, idPrefix, propertyPrefix, titlePrefix);
     181      return;
     182    }
     183    SessionControl sc = dc.getSessionControl();
     184    for (ClonedProperty cp : template.getClonedProperties())
     185    {
     186      String name = cp.getName();
     187      TableColumn tc = new TableColumn(idPrefix + name, propertyPrefix + name, "rep('"+name+"')",
     188          cp.getType(), titlePrefix + cp.getTitle(), cp.getDescription(), "auto", true, true, true,
     189          cp.getAverageMethod(), FormatterFactory.getExtendedPropertyFormatter(sc, cp));
     190        columns.add(tc);
     191    }
     192   
     193  }
     194 
     195 
    173196  @SuppressWarnings("unchecked")
    174197  public static void addExtraColumns(List<TableColumn> columns, DbControl dc, BioAssaySet bas, String idPrefix, String propertyPrefix, String titlePrefix)
  • trunk/src/core/net/sf/basedb/core/ClonedProperty.java

    r5877 r5879  
    4444  implements Comparable<ClonedProperty>
    4545{
     46 
     47  private static final boolean MANDATORY = true;
     48  private static final boolean NULLABLE = true;
     49 
     50  /**
     51    The property name of the "static" property {@link ReporterData#getId()}.
     52    This property is mandatory in clone templates.
     53  */
     54  public static String ID = "id";
     55
     56  /**
     57    The property name of the "static" property {@link ReporterData#getVersion()}.
     58    This property is mandatory in clone templates.
     59  */
     60  public static String VERSION = "version";
     61
     62  /**
     63    The property name of the "static" property {@link ReporterData#getExternalId()}.
     64    This property is mandatory in clone templates.
     65  */
     66  public static String EXTERNAL_ID = "externalId";
     67
    4668  /**
    4769    The property name of the "static" property {@link ReporterData#getName()}
     
    6688  {
    6789    ClonedProperty property = null;
    68     if (NAME.equals(name))
     90    if (ID.equals(name))
     91    {
     92      property = new ClonedProperty(ID, "Id", "The internal id of the reporter", "id",
     93        Type.INT, 0, !NULLABLE, AverageMethod.NONE, MANDATORY);
     94    }
     95    else if (VERSION.equals(name))
     96    {
     97      property = new ClonedProperty(VERSION, "Version", "The internal version number of the reporter", "version",
     98        Type.INT, 0, !NULLABLE, AverageMethod.NONE, MANDATORY);
     99    }
     100    else if (EXTERNAL_ID.equals(name))
     101    {
     102      property = new ClonedProperty(EXTERNAL_ID, "External ID", "The external id of the reporter", "external_id",
     103        Type.STRING, ReporterData.MAX_EXTERNAL_ID_LENGTH, !NULLABLE, AverageMethod.NONE, MANDATORY);
     104    }
     105    else if (NAME.equals(name))
    69106    {
    70107      property = new ClonedProperty(NAME, "Name", "The name of the reporter", "name",
    71         Type.STRING, ReporterData.MAX_NAME_LENGTH, false, AverageMethod.NONE);
     108        Type.STRING, ReporterData.MAX_NAME_LENGTH, !NULLABLE, AverageMethod.NONE, !MANDATORY);
    72109    }
    73110    else if (SYMBOL.equals(name))
    74111    {
    75112      property = new ClonedProperty(SYMBOL, "Symbol", "", "symbol",
    76         Type.STRING, ReporterData.MAX_SYMBOL_LENGTH, true, AverageMethod.NONE);
     113        Type.STRING, ReporterData.MAX_SYMBOL_LENGTH, NULLABLE, AverageMethod.NONE, !MANDATORY);
    77114    }
    78115    else
     
    130167  public static List<ClonedProperty> getAll()
    131168  {
    132     List<ExtendedProperty> extended = ExtendedProperties.getProperties("ReporterData");
    133     List<ClonedProperty> all = new ArrayList<ClonedProperty>(extended.size() + 2);
    134    
    135     for (ExtendedProperty ep : extended)
    136     {
    137       all.add(new ClonedProperty(ep));
    138     }
     169    List<ClonedProperty> all = getAllMandatory();
     170    // Other static properties
    139171    all.add(createFromRegular(NAME));
    140172    all.add(createFromRegular(SYMBOL));
     173    // All extended properties
     174    List<ExtendedProperty> extended = ExtendedProperties.getProperties("ReporterData");
     175    for (ExtendedProperty ep : extended)
     176    {
     177      all.add(new ClonedProperty(ep));
     178    }
    141179    Collections.sort(all);
    142180    return all;
    143181  }
    144182 
     183  /**
     184    Get a list with all mandatory properties that must be cloned.
     185  */
     186  public static List<ClonedProperty> getAllMandatory()
     187  {
     188    List<ClonedProperty> mandatory = new ArrayList<ClonedProperty>();
     189    mandatory.add(createFromRegular(ID));
     190    mandatory.add(createFromRegular(VERSION));
     191    mandatory.add(createFromRegular(EXTERNAL_ID));
     192    return mandatory;
     193  }
     194 
     195  private final boolean isMandatory;
    145196  private final boolean isExtendedProperty;
    146197 
     
    149200  */
    150201  private ClonedProperty(String propertyName, String title, String description,
    151       String column, Type valueType, int length, boolean nullable, AverageMethod averageMethod)
     202      String column, Type valueType, int length, boolean nullable, AverageMethod averageMethod, boolean isMandatory)
    152203  {
    153204    super(propertyName, title, description, column,
     
    155206      averageMethod, null);
    156207    this.isExtendedProperty = false;
     208    this.isMandatory = isMandatory;
    157209  }
    158210 
     
    167219      p.getAverageMethod(), null);
    168220    this.isExtendedProperty = true;
     221    this.isMandatory = false;
    169222  }
    170223 
     
    181234      AverageMethod.fromValue(d.getAverageMethod()), null);
    182235    this.isExtendedProperty = d.isExtendedProperty();
     236    this.isMandatory = d.isMandatory();
    183237  }
    184238 
     
    197251    data.setAverageMethod(getAverageMethod().getValue());
    198252    data.setExtendedProperty(isExtendedProperty());
     253    data.setMandatory(isMandatory());
    199254    return data;
    200255  }
     
    206261  {
    207262    return isExtendedProperty;
     263  }
     264 
     265  /**
     266    Check if this property is mandatory in all clone templates.
     267  */
     268  public boolean isMandatory()
     269  {
     270    return isMandatory;
    208271  }
    209272 
     
    248311    -----------------------------
    249312  */
     313  /**
     314    Sort mandatory properties before, nonmadatory.
     315  */
    250316  @Override
    251317  public int compareTo(ClonedProperty o)
    252318  {
     319    if (isMandatory() != o.isMandatory())
     320    {
     321      return isMandatory() ? -1 : 1;
     322    }
    253323    return getName().compareTo(o.getName());
    254324  }
  • trunk/src/core/net/sf/basedb/core/DynamicJoin.java

    r5320 r5879  
    5252  private final VirtualTable left;
    5353  private final VirtualTable right;
    54   private final VirtualColumn[] columns;
     54  private final VirtualColumn[] leftColumns;
     55  private final VirtualColumn[] rightColumns;
    5556  private int hashCode;
    5657 
     
    6768  DynamicJoin(VirtualDb vdb, JoinType joinType, VirtualTable right, VirtualColumn... columns)
    6869  {
    69     this(vdb, joinType, null, right, columns);
     70    this(vdb, joinType, null, columns, right, columns);
    7071  }
    7172 
     
    8586    VirtualColumn... columns)
    8687  {
     88    this(vdb, joinType, left, columns, right, columns);
     89  }
     90 
     91  /**
     92    Create a new join between two tables with possible different colum names in
     93    the left and right tables.
     94    @param vdb The virtual database where the joined table is located
     95    @param joinType The type of join
     96    @param left The table to join from (or null to join from the root table)
     97    @param leftColumns The columns in the left table to use in the join
     98    @param right The table to join to
     99    @param rightColumns The columns in the right table (must be of same length as leftColumns)
     100    @since 3.1
     101   */
     102  DynamicJoin(VirtualDb vdb, JoinType joinType, VirtualTable left, VirtualColumn[] leftColumns,
     103      VirtualTable right, VirtualColumn[] rightColumns)
     104  {
    87105    this.vdb = vdb;
    88106    this.joinType = joinType;
    89107    this.left = left;
    90108    this.right = right;
    91     this.columns = columns;
     109    this.leftColumns = leftColumns;
     110    this.rightColumns = rightColumns;
    92111  }
    93112 
     
    109128      sb.append(" ON ");
    110129      String deliminator = "";
    111       for (VirtualColumn column : columns)
     130      for (int i = 0; i < leftColumns.length; ++i)
    112131      {
    113         String qualifiedColumn = HibernateUtil.quote(column.getColumn());
     132        String rightColumn = HibernateUtil.quote(rightColumns[i].getColumn());
     133        String leftColumn = HibernateUtil.quote(leftColumns[i].getColumn());
    114134        sb.append(deliminator);
    115         sb.append(rightAlias).append(".").append(qualifiedColumn);
    116         sb.append(" = ").append(leftAlias).append(".").append(qualifiedColumn);
     135        sb.append(rightAlias).append(".").append(rightColumn);
     136        sb.append(" = ").append(leftAlias).append(".").append(leftColumn);
    117137        deliminator = " AND ";
    118138      }
     
    161181      StringBuilder sb = new StringBuilder();
    162182      String deliminator = "";
    163       for (VirtualColumn column : columns)
     183      for (int i = 0; i < leftColumns.length; ++i)
    164184      {
    165         String qualifiedColumn = HibernateUtil.quote(column.getColumn());
     185        String rightColumn = HibernateUtil.quote(rightColumns[i].getColumn());
     186        String leftColumn = HibernateUtil.quote(leftColumns[i].getColumn());
    166187        sb.append(deliminator);
    167         sb.append(leftAlias).append(".").append(qualifiedColumn);
    168         sb.append(" = ").append(rightAlias).append(".").append(qualifiedColumn);
     188        sb.append(leftAlias).append(".").append(leftColumn);
     189        sb.append(" = ").append(rightAlias).append(".").append(rightColumn);
    169190        if (joinType == JoinType.LEFT) sb.append("(+)");
    170191        deliminator = " AND ";
     
    193214    sb.append(" ON ");
    194215    String deliminator = "";
    195     for (VirtualColumn column : columns)
     216    for (int i = 0; i < leftColumns.length; ++i)
    196217    {
    197218      sb.append(deliminator);
    198       sb.append(rightAlias).append(".").append(column.getName());
    199       sb.append(" = ").append(leftAlias).append(column.getName());
     219      sb.append(rightAlias).append(".").append(rightColumns[i].getName());
     220      sb.append(" = ").append(leftAlias).append(leftColumns[i].getName());
    200221      deliminator = " AND ";
    201222    }
     
    212233    if (other == null || this.getClass() != other.getClass()) return false;
    213234    DynamicJoin o = (DynamicJoin)other;
    214     return EqualsHelper.equals(vdb, o.vdb) && left == o.left && right == o.right &&
    215       joinType == o.joinType && EqualsHelper.invariantEquals(columns, o.columns);
     235    return EqualsHelper.equals(vdb, o.vdb) && left == o.left && right == o.right && joinType == o.joinType &&
     236      EqualsHelper.invariantEquals(leftColumns, o.leftColumns) && EqualsHelper.invariantEquals(rightColumns, o.rightColumns);
    216237  }
    217238  @Override
     
    221242    {
    222243      hashCode = EqualsHelper.hashCode(vdb, left, right, joinType) +
    223         EqualsHelper.hashCode(columns);
     244        EqualsHelper.hashCode(leftColumns) + EqualsHelper.hashCode(rightColumns);
    224245    }
    225246    return hashCode;
  • trunk/src/core/net/sf/basedb/core/DynamicPositionQuery.java

    r5876 r5879  
    153153    to select reporter data or restrict the results based on reporter
    154154    information.
     155    <p>
     156    NOTE! Since BASE 3.1 this method automatically join to the cloned reporter
     157    table if available. Use {@link #joinReporters(JoinType, boolean)}, or
     158    {@link #setUseClonedReporters(boolean)} with a FALSE value to force using
     159    the master reporters table.
     160
    155161    @param joinType The type of join. Can not be null.
    156162    @throws InvalidDataException If joinType is null.
     
    159165    @see Dynamic#reporter(String)
    160166  */
     167  @Deprecated
    161168  public void joinReporters(JoinType joinType)
    162169    throws InvalidDataException, BaseException
    163170  {
     171    joinReporters(joinType, useClonedReporters());
     172  }
     173 
     174  /**
     175    Join information about reporters in the query. If the useCloned
     176    parameter is TRUE cloned reporter annotations are used if available,
     177    otherwise the master reporter annotations are used.
     178 
     179    @param joinType The type of join. Can not be null.
     180    @throws InvalidDataException If joinType parameter is null.
     181    @see Dynamic#selectReporter(String)
     182    @see Dynamic#reporter(String)
     183    @since 3.1
     184  */
     185  public void joinReporters(JoinType joinType, boolean useCloned)
     186  {
    164187    if (joinType == null) throw new InvalidUseOfNullException("joinType");
    165     if (!joinedItems.contains(RealTable.REPORTERS))
    166     {
    167       join(new RealJoin(joinType, VirtualTable.POSITION, RealTable.REPORTERS,
    168         VirtualColumn.REPORTER_ID));
    169       joinedItems.add(RealTable.REPORTERS);
    170     }
     188    if (useCloned && hasClonedReporters())
     189    {
     190      if (!joinedItems.contains(VirtualTable.CLONED_REPORTERS))
     191      {
     192        VirtualColumn[] posColumns = new VirtualColumn[] { VirtualColumn.REPORTER_ID };
     193        VirtualColumn[] cloneColumns = new VirtualColumn[] { VirtualColumn.REPORTER_ID_PK };
     194        join(new DynamicJoin(getVirtualDb(), joinType,
     195            VirtualTable.POSITION, posColumns,
     196            VirtualTable.CLONED_REPORTERS, cloneColumns));
     197        joinedItems.add(VirtualTable.CLONED_REPORTERS);
     198      }
     199    }
     200    else
     201    {
     202      if (!joinedItems.contains(RealTable.REPORTERS))
     203      {
     204        join(new RealJoin(joinType, VirtualTable.POSITION, RealTable.REPORTERS,
     205          VirtualColumn.REPORTER_ID));
     206        joinedItems.add(RealTable.REPORTERS);
     207      }
     208    }
     209   
    171210  }
    172211 
  • trunk/src/core/net/sf/basedb/core/DynamicPositionQueryJoiners.java

    r5711 r5879  
    182182    public void joinIfNeeded(DynamicPositionQuery query, ReporterPropertyExpression element)
    183183    {
    184       query.joinReporters(joinType);
     184      query.joinReporters(joinType, element.useCloned(query));
    185185    }
    186186    // -------------------------------------------
  • trunk/src/core/net/sf/basedb/core/DynamicQuery.java

    r5876 r5879  
    5656  private final VirtualTable rootTable;
    5757  private final IntensityTransform transform;
     58  private final boolean hasClonedReporters;
     59  private boolean useClonedReporters;
    5860
    5961  /**
     
    6971    this.rootTable = rootTable;
    7072    this.transform = transform;
     73    this.hasClonedReporters = virtualDb.hasClonedReporters();
     74    this.useClonedReporters = hasClonedReporters;
    7175    restrictPermanent(
    7276      new DynamicRestriction(VirtualColumn.CUBE, cube.getCubeNo())
     
    8690    this.cube = null;
    8791    this.virtualDb = vdb;
     92    this.hasClonedReporters = vdb.hasClonedReporters();
    8893    this.rootTable = rootTable;
    8994    this.transform = null;
     
    105110 
    106111  /**
     112    Check if the virtual database that this query is using has
     113    cloned reporter annotations or not.
     114    @since 3.1
     115  */
     116  public boolean hasClonedReporters()
     117  {
     118    return hasClonedReporters;
     119  }
     120 
     121  /**
     122    Checks if this query is using cloned reporter or not by default.
     123    The default setting is to use cloned reporters if they are available
     124    in the experiment.
     125   
     126    @return TRUE if this query is using cloned reporters, FALSE if not
     127    @since 3.1
     128  */
     129  public boolean useClonedReporters()
     130  {
     131    return useClonedReporters;
     132  }
     133 
     134  /**
     135    Set if cloned reporters should be used by default or not.
     136    @param useClonedReporters TRUE to use cloned reporters by default, FALSE
     137      to use the master reporters
     138    @since 3.1
     139  */
     140  public void setUseClonedReporters(boolean useClonedReporters)
     141  {
     142    this.useClonedReporters = hasClonedReporters && useClonedReporters;
     143  }
     144 
     145  /**
    107146    Create custom JEP function that can be used with the current
    108147    query. The actual function need to implement either {@link JepExpressionFunction}
     
    120159    return cube;
    121160  }
    122   VirtualDb getVirtualDb()
     161  /**
     162    Get the virtual database that this query is using.
     163    @return A virtual database item
     164    @since 3.1
     165  */
     166  public VirtualDb getVirtualDb()
    123167  {
    124168    return virtualDb;
  • trunk/src/core/net/sf/basedb/core/DynamicSpotQuery.java

    r5711 r5879  
    195195    to select reporter data or restrict the results based on reporter
    196196    information.
     197    <p>
     198    NOTE! Since BASE 3.1 this method automatically join to the cloned reporter
     199    table if available. Use {@link #joinReporters(JoinType, boolean)}, or
     200    {@link #setUseClonedReporters(boolean)} with a FALSE value to force using
     201    the master reporters table.
     202   
    197203    @param joinType The type of join. Can not be null.
    198204    @throws InvalidDataException If joinType parameter is null.
    199205    @see Dynamic#selectReporter(String)
    200206    @see Dynamic#reporter(String)
    201   */
     207    @deprecated In 3.1, use {@link #joinReporters(JoinType, boolean)} instead
     208  */
     209  @Deprecated
    202210  public void joinReporters(JoinType joinType)
    203211    throws InvalidDataException
     212  {
     213    joinReporters(joinType, useClonedReporters());
     214  }
     215 
     216  /**
     217    Join information about reporters in the query. If the useCloned
     218    parameter is TRUE cloned reporter annotations are used if available,
     219    otherwise the master reporter annotations are used.
     220
     221    @param joinType The type of join. Can not be null.
     222    @throws InvalidDataException If joinType parameter is null.
     223    @see Dynamic#selectReporter(String)
     224    @see Dynamic#reporter(String)
     225    @since 3.1
     226  */
     227  public void joinReporters(JoinType joinType, boolean useCloned)
    204228  {
    205229    if (joinType == null) throw new InvalidUseOfNullException("joinType");
     
    210234      joinedItems.add(VirtualTable.POSITION);
    211235    }
    212     if (!joinedItems.contains(RealTable.REPORTERS))
    213     {
    214       join(new RealJoin(joinType, VirtualTable.POSITION, RealTable.REPORTERS,
    215         VirtualColumn.REPORTER_ID));
    216       joinedItems.add(RealTable.REPORTERS);
     236    if (useCloned && hasClonedReporters())
     237    {
     238      if (!joinedItems.contains(VirtualTable.CLONED_REPORTERS))
     239      {
     240        VirtualColumn[] posColumns = new VirtualColumn[] { VirtualColumn.REPORTER_ID };
     241        VirtualColumn[] cloneColumns = new VirtualColumn[] { VirtualColumn.REPORTER_ID_PK };
     242        join(new DynamicJoin(getVirtualDb(), joinType,
     243            VirtualTable.POSITION, posColumns,
     244            VirtualTable.CLONED_REPORTERS, cloneColumns));
     245        joinedItems.add(VirtualTable.CLONED_REPORTERS);
     246      }
     247    }
     248    else
     249    {
     250      if (!joinedItems.contains(RealTable.REPORTERS))
     251      {
     252        join(new RealJoin(joinType, VirtualTable.POSITION, RealTable.REPORTERS,
     253          VirtualColumn.REPORTER_ID));
     254        joinedItems.add(RealTable.REPORTERS);
     255      }
    217256    }
    218257  }
  • trunk/src/core/net/sf/basedb/core/DynamicSpotQueryJoiners.java

    r4517 r5879  
    195195    public void joinIfNeeded(DynamicSpotQuery query, ReporterPropertyExpression element)
    196196    {
    197       query.joinReporters(joinType);
     197      query.joinReporters(joinType, element.useCloned(query));
    198198    }
    199199    // -------------------------------------------
  • trunk/src/core/net/sf/basedb/core/QueryExecutor.java

    r5689 r5879  
    8787    @return The result from {@link PreparedStatement#executeQuery()}
    8888    @throws InterruptedException If this thread was interrupted
     89    @throws SQLException If there was an error executing the SQL statement
    8990  */
    9091  public static ResultSet executeQuery(PreparedStatement ps, SessionControl sc)
    91     throws InterruptedException
     92    throws InterruptedException, SQLException
    9293  {
    9394    return getFutureResult(new FutureResultSet(ps), new CancelableStatement(ps), sc);
     
    103104  */
    104105  public static int executeUpdate(PreparedStatement ps, SessionControl sc)
    105     throws InterruptedException
     106    throws InterruptedException, SQLException
    106107  {
    107108    Integer result = getFutureResult(new FutureUpdate(ps), new CancelableStatement(ps), sc);
     
    123124    throws InterruptedException
    124125  {
    125     return getFutureResult(new FutureScrollIterator<T>(clazz, query),
    126       new CancelableStatelessSession(session), sc);
     126    try
     127    {
     128      return getFutureResult(new FutureScrollIterator<T>(clazz, query),
     129        new CancelableStatelessSession(session), sc);
     130    }
     131    catch (SQLException ex)
     132    {
     133      throw new BaseException(ex);
     134    }
    127135  }
    128136
     
    143151    throws InterruptedException
    144152  {
    145     return getFutureResult(new FutureItem<T>(clazz, query),
    146       new CancelableStatelessSession(session), sc);
     153    try
     154    {
     155      return getFutureResult(new FutureItem<T>(clazz, query),
     156        new CancelableStatelessSession(session), sc);
     157    }
     158    catch (SQLException ex)
     159    {
     160      throw new BaseException(ex);
     161    }
    147162  }
    148163
     
    163178  private static <T> T getFutureResult(Callable<T> callable, Cancelable cancelable,
    164179    SessionControl sc)
    165     throws InterruptedException
     180    throws InterruptedException, SQLException
    166181  {
    167182    Future<T> future = service.submit(callable);
     
    194209    catch (ExecutionException ex)
    195210    {
    196       throw new BaseException(ex.getCause());
     211      if (ex.getCause() instanceof SQLException)
     212      {
     213        throw (SQLException)ex.getCause();
     214      }
     215      else
     216      {
     217        throw new BaseException(ex.getCause());
     218      }
    197219    }
    198220    return result;
  • trunk/src/core/net/sf/basedb/core/ReporterCloneBatcher.java

    r5878 r5879  
    2727
    2828import net.sf.basedb.core.data.ReporterCloneTemplateData;
    29 import net.sf.basedb.core.hibernate.TypeWrapper;
    3029import net.sf.basedb.core.query.Dynamic;
    3130import net.sf.basedb.core.query.JoinType;
     
    299298  {
    300299
     300    // Create VirtualColumn representations of all cloned properties
     301    VirtualColumn[] columns = VirtualTable.CLONED_REPORTERS.getColumns(virtualDb);
     302   
    301303    insertSqlStatement =  BatchUtil.buildInsertSql(
    302304      virtualDb,
    303305      VirtualTable.CLONED_REPORTERS,
    304       VirtualTable.CLONED_REPORTERS.getColumns(virtualDb),
     306      columns,
    305307      new Object[] {}
    306308    );
     
    316318  private DynamicPositionQuery buildSelectQuery()
    317319  {
    318    
    319     List<ClonedProperty> properties = virtualDb.getReporterCloneTemplate().getClonedProperties();
    320 
    321     parameterTypes = new int[4+properties.size()];
     320    List<ClonedProperty> cloned = virtualDb.getReporterCloneTemplate().getClonedProperties();
     321    parameterTypes = new int[cloned.size()+1];
    322322   
    323323    DynamicPositionQuery query = new DynamicPositionQuery(experiment);
     324    query.setUseClonedReporters(false);
    324325    query.joinReporters(JoinType.INNER);
    325326    query.setDistinct(true);
    326327
    327328    query.order(Orders.asc(Dynamic.reporter("id")));
    328    
    329     query.select(Selects.expression(Dynamic.reporter("id"), "id", true));
    330     query.select(Selects.expression(Dynamic.reporter("version"), "version"));
    331     query.select(Selects.expression(Dynamic.reporter("externalId"), "externalId"));
    332     parameterTypes[1] = TypeWrapper.INTEGER.getSQLType();
    333     parameterTypes[2] = TypeWrapper.INTEGER.getSQLType();
    334     parameterTypes[3] = TypeWrapper.STRING.getSQLType();
    335    
    336     int index = 4;
    337     for (ClonedProperty cp : properties)
    338     {
    339       query.select(Selects.expression(Dynamic.reporter(cp.getName()), "cp"+index));
    340       parameterTypes[index] = cp.getType().getSQLType();
     329
     330    int index = 1;
     331    for (ClonedProperty cp : cloned)
     332    {
     333      query.select(Selects.expression(Dynamic.reporter(cp.getName()), "cp" + index, cp.getName().equals(ClonedProperty.ID)));
     334      parameterTypes[index] = cp.getType().getTypeWrapper().getSQLType();
    341335      index++;
    342336    }
    343    
    344337    return query;
    345338  }
  • trunk/src/core/net/sf/basedb/core/ReporterCloneTemplate.java

    r5878 r5879  
    7474    t.setName("New reporter clone template");
    7575    t.getData().setEntryDate(new Date());
     76    for (ClonedProperty cp : ClonedProperty.getAll())
     77    {
     78      if (cp.isMandatory()) t.addClonedProperty(cp);
     79    }
    7680    return t;
    7781  }
     
    147151    }
    148152    super.initPermissions(granted, denied);
     153  }
     154 
     155  /**
     156   
     157  */
     158  @Override
     159  PluginPermission getPluginPermissions()
     160  {
     161    if (isLocked())
     162    {
     163      return new PluginPermission(Permission.grant(Permission.READ), Permission.deny(Permission.WRITE));
     164    }
     165    return super.getPluginPermissions();
    149166  }
    150167 
     
    263280    checkPermission(Permission.WRITE);
    264281    if (propertyName == null) throw new InvalidUseOfNullException("propertyName");
    265     getData().getProperties().remove(propertyName);
     282    ClonedProperty cp = getClonedProperty(propertyName);
     283    if (cp != null)
     284    {
     285      if (cp.isMandatory())
     286      {
     287        throw new PermissionDeniedException("Property is mandatory: " + propertyName);
     288      }
     289      getData().getProperties().remove(propertyName);
     290    }
    266291  }
    267292 
  • trunk/src/core/net/sf/basedb/core/ReporterPropertyExpression.java

    r5384 r5879  
    5555  private final String column;
    5656
     57  private final Boolean useCloned;
     58 
     59  /**
     60    Create a new reporter property expression. The expression
     61    automatically selects if cloned reporter information
     62    should be used or not.
     63    @param property The name of the property
     64  */
    5765  public ReporterPropertyExpression(String property)
    5866    throws InvalidDataException
    5967  {
     68    this(property, null);
     69  }
     70
     71  /**
     72    Create a new reporter property expression. The expression may
     73    be forced to use either the cloned or master reporter information.
     74    @param property The name of the property
     75    @param useCloned TRUE to use cloned reporter information (if available),
     76      FALSE to not use cloned information, null to automatically decide
     77    @since 3.1
     78  */
     79  public ReporterPropertyExpression(String property, Boolean useCloned)
     80  {
    6081    this.property = property;
    6182    this.column = getColumn(property);
     83    this.useCloned = useCloned;
    6284    if (column == null) throw new InvalidDataException("Unknown property '"+property+"' of reporter.");
    6385  }
    64 
     86 
    6587  /*
    6688    From the QueryElement interface
     
    7294    if (query.getQueryType() == QueryType.SQL)
    7395    {
    74       return HibernateUtil.quote(RealTable.REPORTERS.getAlias()) + "." + HibernateUtil.quote(column);
     96      String joinAlias = RealTable.REPORTERS.getAlias();
     97     
     98      if (query instanceof DynamicQuery)
     99      {
     100        DynamicQuery dynamicQuery = (DynamicQuery)query;
     101        if (useCloned(dynamicQuery))
     102        {
     103          if (!dynamicQuery.getVirtualDb().hasClonedReporterProperty(property))
     104          {
     105            throw new InvalidDataException("Reporter property is not cloned: " + property);
     106          }
     107          joinAlias = VirtualTable.CLONED_REPORTERS.getAlias();
     108        }
     109      }
     110      return HibernateUtil.quote(joinAlias) + "." + HibernateUtil.quote(column);
    75111    }
    76112    else
     
    106142    if (other == null || this.getClass() != other.getClass()) return false;
    107143    ReporterPropertyExpression o = (ReporterPropertyExpression)other;
    108     return EqualsHelper.equals(property, o.property);
     144    return EqualsHelper.equals(property, o.property) && useCloned == o.useCloned;
    109145  }
    110146  @Override
    111147  public int hashCode()
    112148  {
    113     return EqualsHelper.hashCode(property);
     149    return EqualsHelper.hashCode(property) + (useCloned ? 1 : 0);
    114150  }
    115151  // -------------------------------------------
     152 
     153  /**
     154    Check if this reporter property should use the cloned
     155    reporter for the given query or not. If the query is using a
     156    virtual database that doesn't have cloned reporters, FALSE is
     157    returned. Othersise, if an explicit request has been made to
     158    use/not use cloned reporters, that value is returned. If
     159    no explicit request has been made, the outcome depends
     160    on the {@link DynamicQuery#useClonedReporters()}.
     161   
     162    @param query The query to check with
     163    @return TRUE if the cloned reporter table should be used, FALSE if not
     164    @since 3.1
     165  */
     166  public boolean useCloned(DynamicQuery query)
     167  {
     168    // Check if the virtual database has cloned reporters
     169    if (!query.hasClonedReporters()) return false;
     170    // Explicit request to use/not use cloned reporters
     171    if (useCloned != null) return useCloned.booleanValue();
     172    // Auto-select based on query
     173    return query.useClonedReporters();
     174  }
    116175 
    117176  private static String getColumn(String property)
  • trunk/src/core/net/sf/basedb/core/VirtualColumn.java

    r5876 r5879  
    250250
    251251  /**
    252     Get a virutal column view of a cloned reporter property.
     252    Get a virtual column view of a cloned reporter property.
    253253    @param property The cloned reporter property
    254254    @return A virtual column representation of the cloned property
     
    257257  public static VirtualColumn clonedProperty(ClonedProperty property)
    258258  {
    259     return new VirtualColumn(property.getName(), property.getColumn(), property.getType().getTypeWrapper(),
    260       property.getLength(), !INDEXED, !UNIQUE, property.isNullable(), !PRIMARY_KEY, false);
     259    VirtualColumn vc = null;
     260    if (property.isMandatory())
     261    {
     262      // Some columns need special handling due to VirtualColumn
     263      // holding more properties (UNIQUE, PRIMARY_KEY, etc.)
     264      // than a ClonedProperty item can
     265      String name = property.getName();
     266      if (ClonedProperty.ID.equals(name))
     267      {
     268        vc = VirtualColumn.REPORTER_ID_PK;
     269      }
     270      else if (ClonedProperty.VERSION.equals(name))
     271      {
     272        vc = VirtualColumn.REPORTER_VERSION;
     273      }
     274      else if (ClonedProperty.EXTERNAL_ID.equals(name))
     275      {
     276        vc = VirtualColumn.REPORTER_EXTERNAL_ID;
     277      }
     278    }
     279    if (vc == null)
     280    {
     281      vc = new VirtualColumn(property.getName(), property.getColumn(), property.getType().getTypeWrapper(),
     282          property.getLength(), !INDEXED, !UNIQUE, property.isNullable(), !PRIMARY_KEY, false);
     283    }
     284    return vc;
    261285  }
    262286 
  • trunk/src/core/net/sf/basedb/core/VirtualDb.java

    r5876 r5879  
    200200  {
    201201    return getData().getReporterCloneTemplate() != null;
     202  }
     203 
     204  /**
     205    Checks if this virtual db has cloned the given reporter property or not.
     206    @param propertyName The name of a reporter property
     207    @since 3.1
     208  */
     209  public boolean hasClonedReporterProperty(String propertyName)
     210  {
     211    return hasClonedReporters() && getData().getReporterCloneTemplate().getProperties().containsKey(propertyName);
    202212  }
    203213 
  • trunk/src/core/net/sf/basedb/core/VirtualTable.java

    r5876 r5879  
    264264      if (!vdb.hasClonedReporters()) return new VirtualColumn[0];
    265265     
    266       VirtualColumn[] defaultColumns = super.getColumns(vdb);
     266      // We load the cloned properties from the template...
     267      // The default columns should be included
    267268      ReporterCloneTemplate cloneTemplate = vdb.getReporterCloneTemplate();
    268269      List<ClonedProperty> properties = cloneTemplate.getClonedProperties();
    269       VirtualColumn[] allColumns = new VirtualColumn[defaultColumns.length + properties.size()];
    270       System.arraycopy(defaultColumns, 0, allColumns, 0, defaultColumns.length);
     270      VirtualColumn[] allColumns = new VirtualColumn[properties.size()];
    271271     
    272       int index = defaultColumns.length;
     272      int index = 0;
    273273      for (ClonedProperty cp : properties)
    274274      {
  • trunk/src/core/net/sf/basedb/core/data/ReporterClonePropertyData.java

    r5877 r5879  
    142142  private boolean extendedProperty;
    143143  /**
    144     If the column is nullable or not.
     144    If the column is an extended or "static" property.
    145145    @hibernate.property column="`extended_property`" type="boolean" not-null="true" update="false"
    146146  */
     
    154154  }
    155155
     156  private boolean mandatory;
     157  /**
     158    If the column is a mandatory that must be in all clone templates.
     159    @hibernate.property column="`mandatory`" type="boolean" not-null="true" update="false"
     160  */
     161  public boolean isMandatory()
     162  {
     163    return mandatory;
     164  }
     165  public void setMandatory(boolean mandatory)
     166  {
     167    this.mandatory = mandatory;
     168  }
     169
    156170}
  • trunk/src/core/net/sf/basedb/core/query/Dynamic.java

    r4889 r5879  
    7575
    7676  /**
    77     Select a column in the reporters table. It is expected that
    78     reporters has been joined to the query.
     77    Select a column in the reporters table. The expression uses cloned
     78    reporter information if available in the current experiment.
     79   
    7980    @param property The name of the property
    8081    @throws InvalidDataException If the property is null
    8182    @see net.sf.basedb.core.DynamicSpotQuery#joinReporters(JoinType)
    8283  */
     84  @Deprecated
    8385  public static Select selectReporter(String property)
    8486    throws InvalidDataException
    8587  {
    86     return Selects.expression(reporter(property), property);
    87   }
    88 
     88    return selectReporter(property, null);
     89  }
     90
     91  /**
     92    Select a column in the reporters table. The expression can be forced
     93    to use cloned or master reporter information.
     94   
     95    @param property The name of the property
     96    @param useCloned TRUE to use cloned reporter information (if available),
     97      FALSE to not use cloned information, null to automatically decide
     98   
     99    @throws InvalidDataException If the property is null
     100    @see net.sf.basedb.core.DynamicSpotQuery#joinReporters(JoinType, boolean)
     101    @see net.sf.basedb.core.DynamicQuery#setUseClonedReporters(boolean)
     102    @since 3.1
     103  */
     104  public static Select selectReporter(String property, Boolean useCloned)
     105    throws InvalidDataException
     106  {
     107    return Selects.expression(reporter(property, useCloned), property);
     108  }
     109 
    89110  /**
    90111    Select a column in the raw data table. It is expected that
     
    150171  /**
    151172    Create an expression representing a property of a reporter.
    152     expression = reporter.property. It is expected that the
    153     reporters table is already joined by the query.
    154 
    155     @param property The name of the property
    156     @return The new expression
    157     @throws InvalidDataException If the property is null
    158     @see net.sf.basedb.core.DynamicSpotQuery#joinReporters(JoinType)
    159   */
     173    expression = reporter.property. The expression uses cloned
     174    reporter information if available in the current experiment.
     175
     176    @param property The name of the property
     177    @return The new expression
     178    @throws InvalidDataException If the property is null
     179    @see net.sf.basedb.core.DynamicSpotQuery#joinReporters(JoinType, boolean)
     180    @see net.sf.basedb.core.DynamicQuery#setUseClonedReporters(boolean)
     181  */
     182  @Deprecated
    160183  public static Expression reporter(String property)
    161184    throws InvalidDataException
    162185  {
     186    return reporter(property, null);
     187  }
     188 
     189  /**
     190    Create an expression representing a property of a reporter.
     191    expression = reporter.property. The expression can be forced
     192    to use cloned or master reporter information.
     193   
     194    @param property The name of the property
     195    @param useCloned TRUE to use cloned reporter information (if available),
     196      FALSE to not use cloned information, null to automatically decide
     197    @return The new expression
     198    @throws InvalidDataException If the property is null
     199    @see net.sf.basedb.core.DynamicSpotQuery#joinReporters(JoinType, boolean)
     200    @see net.sf.basedb.core.DynamicQuery#setUseClonedReporters(boolean)
     201    @since 3.1
     202  */
     203  public static Expression reporter(String property, Boolean useCloned)
     204  {
    163205    if (property == null) throw new InvalidUseOfNullException("property");
    164     return new ReporterPropertyExpression(property);
     206    return new ReporterPropertyExpression(property, useCloned);
    165207  }
    166208 
  • trunk/www/admin/reporterclonetemplates/edit_template.jsp

    r5877 r5879  
    6464  {
    6565    title = "Create reporter clone template";
    66     clonedProperties = Collections.emptyList();
     66    clonedProperties = ClonedProperty.getAllMandatory();
    6767    cc.removeObject("item");
    6868  }
     
    132132    }
    133133   
    134     function moveBetween(list1, list2)
     134    function moveBetween(list1, list2, exceptMandatory)
    135135    {
    136136      var moved = 0;
     
    139139        if (list1.options[i].selected)
    140140        {
    141           moved++;
    142           list2.options[list2.options.length] = new Option(list1.options[i].text, list1.options[i].value, false, true);
    143           list1.options[i] = null;
    144           i--;
     141          if (exceptMandatory && list1.options[i].text.indexOf('×') > 0)
     142          {
     143            alert(list1.options[i].text + ' is mandatory');
     144          }
     145          else
     146          {
     147            moved++;
     148            list2.options[list2.options.length] = new Option(list1.options[i].text, list1.options[i].value, false, true);
     149            list1.options[i] = null;
     150            i--;
     151          }
    145152        }
    146153      }
     
    173180              <b>Cloned</b><br>
    174181              <select name="cloned_properties" multiple size="12" style="width: 100%;"
    175                 ondblclick="moveBetween(document.forms['template'].cloned_properties, document.forms['template'].uncloned_properties)">
     182                ondblclick="moveBetween(document.forms['template'].cloned_properties, document.forms['template'].uncloned_properties, true)">
    176183              <%
    177184              for (ClonedProperty cp : clonedProperties)
    178185              {
    179186                %>
    180                 <option value="<%=cp.getName()%>" title="<%=HTML.encodeTags(cp.getDescription())%>"><%=HTML.encodeTags(cp.getTitle())%>
     187                <option value="<%=cp.getName()%>"
     188                  style="<%=cp.isMandatory() ? "font-weight: bold;" : "" %>
     189                  title="<%=HTML.encodeTags(cp.getDescription())%>"><%=HTML.encodeTags(cp.getTitle())%><%=cp.isMandatory() ? " ×" : ""%>
    181190                <%
    182191              }
     
    193202              /><p>
    194203              <base:button
    195                 onclick="moveBetween(document.forms['template'].cloned_properties, document.forms['template'].uncloned_properties)"
     204                onclick="moveBetween(document.forms['template'].cloned_properties, document.forms['template'].uncloned_properties, true)"
    196205                title="<img src='../../images/move_right.gif' alt='' style='vertical-align: middle;'>"
    197206                tooltip="Do not cloned the selected properties"
     
    207216              for (ClonedProperty cp : ClonedProperty.getAll())
    208217              {
    209                 if (template == null || !template.hasClonedProperty(cp.getName()))
     218                if ((template == null && !cp.isMandatory()) || (template != null && !template.hasClonedProperty(cp.getName())))
    210219                {
    211220                  %>
  • trunk/www/common/expression_builder.jsp

    r5426 r5879  
    2828  import="net.sf.basedb.core.Item"
    2929  import="net.sf.basedb.core.BioAssaySet"
     30  import="net.sf.basedb.core.VirtualDb"
     31  import="net.sf.basedb.core.ReporterCloneTemplate"
    3032  import="net.sf.basedb.core.RawDataType"
    3133  import="net.sf.basedb.core.RawDataTypes"
     
    6870  {
    6971    BioAssaySet bas = bioAssaySetId == -1 ? null : BioAssaySet.getById(dc, bioAssaySetId);
     72    VirtualDb vdb = bas != null ? bas.getExperiment().getVirtualDb() : null;
     73    ReporterCloneTemplate template = vdb != null && vdb.hasClonedReporters() ? vdb.getReporterCloneTemplate() : null;
     74       
    7075    IntensityTransform transform = bas == null ? null : bas.getIntensityTransform();
    7176    int maxRawMappings = bas == null ? 1 : bas.getMaxRawMappingsForSpot();
     
    8287    }
    8388    List<TableColumn> reporterProperties = new LinkedList<TableColumn>();
    84     DynamicUtil.addReporterColumns(reporterProperties, dc, "", "", "");
     89    DynamicUtil.addReporterColumns(reporterProperties, dc, template, "", "", "");
    8590   
    8691    ItemQuery<ReporterList> reporterListQuery = ReporterList.getQuery();
  • trunk/www/views/experiments/spotdata/list_spotdata.jsp

    r5438 r5879  
    108108  DynamicUtil.addExtraColumns(columns, dc, bioAssaySet, "ev", "#", "[Xtra] ");
    109109  DynamicUtil.addRawDataColumns(columns, dc, rawDataType, "raw.", "$", "[Raw] ");
    110   DynamicUtil.addReporterColumns(columns, dc, "rep.", "@", "[Rep] ");
     110  DynamicUtil.addReporterColumns(columns, dc, experiment.getVirtualDb().getReporterCloneTemplate(), "rep.", "@", "[Rep] ");
    111111  DynamicUtil.SelectedInfo selected = DynamicUtil.getSelectedColumns(cc, columns, false);
    112112  if (bioAssay == null && cc.getSetting("columns").indexOf("COLUMN") >= 0)
Note: See TracChangeset for help on using the changeset viewer.