Changeset 7494


Ignore:
Timestamp:
Jun 4, 2018, 8:42:46 AM (5 years ago)
Author:
Nicklas Nordborg
Message:

Merged patch release 3.12.3 to the trunk.

Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/config/dist/base.config

    r7414 r7494  
    267267# ===================
    268268
    269 # URL to a 'freegeoip' server. Use {IP} as a placeholder for
    270 # the IP address. The service should return a JSON data object.
    271 # Software for running your own server can be downloaded from
    272 # https://github.com/fiorix/freegeoip
    273 # If no service is specified, location lookup will be disabled
    274 geolocation.freegeoip = http://freegeoip.net/json/{IP}
     269# URL to the 'ipstack' (previously 'freegeoip') server. Use {IP} as a
     270# placeholder for the IP address. The service should return a JSON
     271# data object. Before it can be used you need to register and receive
     272# an API key. See https://ipstack.com/ for more information.
     273# Replace [API_KEY] in the URL below and uncomment the setting to
     274# activate geolocation lookup.
     275# geolocation.freegeoip = http://api.ipstack.com/{IP}?access_key=[API_KEY]&output=json
    275276
    276277# A template URL for displaying a map with a marker on a specified location
  • trunk/src/core/net/sf/basedb/core/AnnotationSimpleRestriction.java

    r7461 r7494  
    113113 
    114114  /**
     115    Creates a new annotation restriction for a specific <code>valueType</code>.
     116    The restriction is with a list of values.
     117   
     118    @param alias The alias of a joined item where the annotations are
     119      located or null to use the root entity of the query
     120    @param annotationType The annotation type to use in the query
     121      @param operator The operator, it must be one of the expression
     122      operators, EQ, NEQ, etc., not a boolean operator, AND, OR, etc.
     123      @param values The list of values that should be used in the query, they must be of the
     124      correct value type for the annotation as defined by the
     125      {@link AnnotationType#getValueType()} property.
     126    @param options Options that specify which annotations to consider when searching
     127      @throws InvalidDataException If any of the parameters are null
     128      or not follow the rules above
     129    @since 3.12.3
     130  */
     131  public AnnotationSimpleRestriction(String alias, AnnotationType annotationType, Operator operator, List<Object> values,
     132    Options options)
     133    throws InvalidDataException
     134  {
     135    super(alias, annotationType, options);
     136    if (operator == null) throw new InvalidUseOfNullException("operator");
     137    if (values == null) throw new InvalidUseOfNullException("values");
     138    if (!operator.isExpressionOperator())
     139    {
     140      throw new InvalidDataException("Invalid operator for expression: "+operator);
     141    }
     142    for (Object obj : values)
     143    {
     144      if (obj != null && !valueType.isCorrectType(obj) && !(valueType.isNumerical() && obj instanceof Number))
     145      {
     146        throw new InvalidDataException("Value '"+obj+"' is a "+
     147          obj.getClass()+", not a "+valueType);
     148      }
     149    }
     150    this.operator = operator;
     151    this.value = null;
     152    this.values = values;
     153  }
     154
     155 
     156  /**
    115157    @since 2.4
    116158    @deprecated in 3.5; Use {@link #AnnotationSimpleRestriction(String, int, Type, Operator, Object, boolean, boolean)} instead
     
    163205  /**
    164206    @since 3.5
    165     @deprecated In 3.11, use {@link #AnnotationSimpleRestriction(String, AnnotationType, Operator, Object, AnnotationRestriction.Options)} instead
     207    @deprecated In 3.11, use {@link #AnnotationSimpleRestriction(String, AnnotationType, Operator, List, AnnotationRestriction.Options)} instead
    166208  */
    167209  @Deprecated
  • trunk/src/core/net/sf/basedb/core/SessionControl.java

    r7452 r7494  
    350350  }
    351351 
    352   GeoLocation getLocation()
    353   {
    354     if (!locationLoaded)
     352  GeoLocation getLocation(AuthenticationMethod authMeth)
     353  {
     354    if (!locationLoaded && authMeth != null && authMeth != AuthenticationMethod.INTERNAL)
    355355    {
    356356      locationLoaded = true;
     
    895895    device.setLastUsed(now);
    896896    device.setLastRemoteId(getRemoteId());
    897     GeoLocation loc = getLocation();
     897    GeoLocation loc = getLocation(authUser.getAuthenticationMethod());
    898898    if (loc == null) loc = new GeoLocation(); // To force 'null' on the location fields
    899899    device.setLocation(loc.toString());
     
    10841084    sessionData.setLoginComment(comment);
    10851085    sessionData.setRemoteId(getRemoteId());
    1086     GeoLocation loc = getLocation();
     1086    GeoLocation loc = getLocation(authenticationMethod);
    10871087    if (loc != null)
    10881088    {
  • trunk/src/core/net/sf/basedb/util/GeoLocation.java

    r7415 r7494  
    240240     
    241241      HttpEntity entity = response.getEntity();
    242       Header contentType = entity.getContentType();
    243       if (contentType != null && !"application/json".equals(contentType.getValue()))
    244       {
    245         throw new RuntimeException("Unexpected content type: "+contentType.getValue());
     242      Header contentTypeHeader = entity.getContentType();
     243      String contentType = contentTypeHeader != null ? contentTypeHeader.getValue() : null;
     244      if (contentType != null && !contentType.contains("application/json"))
     245      {
     246        throw new RuntimeException("Unexpected content type: "+contentType);
    246247      }
    247248     
  • trunk/src/core/net/sf/basedb/util/formatter/PropertyFilterFormatter.java

    r6841 r7494  
    112112      sb.append(")");
    113113    }
    114     else if (property.equals("itemSubtype"))
    115     {
    116       // Special handling to display name of subtype
     114    else if (property.equals("bioWell.row") || property.equals("bioWell.column"))
     115    {
     116      WellCoordinateFormatter formatter = new WellCoordinateFormatter(property.equals("bioWell.row"));
    117117      sb.append(property).append(" ").append(operator).append(" ");
    118       List<Object> subtypes = filter.getValuesAsObjects();
    119       if (subtypes.size() > 1) sb.append("(");
    120       if (subtypes.size() == 0) sb.append("null");
     118      List<Object> selected = filter.getValuesAsObjects();
     119      if (selected.size() > 1) sb.append("(");
     120      if (selected.size() == 0) sb.append("null");
    121121      String sep = "";
    122       for (Object id : subtypes)
     122      for (Object index : selected)
    123123      {
    124124        sb.append(sep);
    125125        sep = ", ";
    126         sb.append(nameOfItem(dc, Item.ITEMSUBTYPE, (Integer)id, true));
    127       }
    128       if (subtypes.size() > 1) sb.append(")");
     126        sb.append(formatter.format((Integer)index));
     127      }
     128      if (selected.size() > 1) sb.append(")");
     129    }
     130    else if (property.equals("parentType"))
     131    {
     132      sb.append(property).append(" ").append(operator).append(" ");
     133      List<Object> selected = filter.getValuesAsObjects();
     134      if (selected.size() > 1) sb.append("(");
     135      if (selected.size() == 0) sb.append("null");
     136      String sep = "";
     137      for (Object index : selected)
     138      {
     139        sb.append(sep);
     140        sep = ", ";
     141        sb.append(Item.fromValue((Integer)index).toString());
     142      }
     143      if (selected.size() > 1) sb.append(")");
    129144    }
    130145    else
    131146    {
    132       if (property.startsWith("&") || property.startsWith("@") || property.startsWith("!"))
    133       {
    134         property = property.substring(1);
    135       }
    136       sb.append(property).append(" ").append(operator).append(" ");
    137       if (operator.isListOperator() && value != null)
    138       {
    139         appendListOfValues(sb, value, quote);
     147      Item nameOfItemType = null;
     148      if (property.equals("itemSubtype") || property.endsWith(".itemSubtype"))
     149      {
     150        // Special handling to display name of subtype
     151        nameOfItemType = Item.ITEMSUBTYPE;
     152      }
     153      else if (property.equals("platform"))
     154      {
     155        // Special handling to display name of platform
     156        nameOfItemType = Item.PLATFORM;
     157      }
     158      if (nameOfItemType != null)
     159      {
     160        sb.append(property).append(" ").append(operator).append(" ");
     161        List<Object> itemIds = filter.getValuesAsObjects();
     162        if (itemIds.size() > 1) sb.append("(");
     163        if (itemIds.size() == 0) sb.append("null");
     164        String sep = "";
     165        for (Object id : itemIds)
     166        {
     167          sb.append(sep);
     168          sep = ", ";
     169          sb.append(nameOfItem(dc, nameOfItemType, (Integer)id, true));
     170        }
     171        if (itemIds.size() > 1) sb.append(")");
    140172      }
    141173      else
    142174      {
    143         if (filter.getValueType().isTemporal())
    144         {
    145           value = dateFormatter.format((Date)Type.DATE.parseString(value));
    146         }
    147         sb.append(quote).append(value).append(quote);
     175        if (property.startsWith("&") || property.startsWith("@") || property.startsWith("!"))
     176        {
     177          property = property.substring(1);
     178        }
     179        sb.append(property).append(" ").append(operator).append(" ");
     180        if (operator.isListOperator() && value != null)
     181        {
     182          appendListOfValues(sb, value, quote);
     183        }
     184        else
     185        {
     186          if (filter.getValueType().isTemporal())
     187          {
     188            value = dateFormatter.format((Date)Type.DATE.parseString(value));
     189          }
     190          sb.append(quote).append(value).append(quote);
     191        }
    148192      }
    149193    }
  • trunk/src/core/net/sf/basedb/util/overview/loader/DerivedBioAssayLoader.java

    r7303 r7494  
    5050import net.sf.basedb.util.overview.OverviewUtil;
    5151import net.sf.basedb.util.overview.Validator;
     52import net.sf.basedb.util.overview.filter.BasicItemFilter;
    5253import net.sf.basedb.util.overview.filter.ItemTypeFilter;
    5354import net.sf.basedb.util.overview.node.ChildNodeDirection;
     
    157158  protected void loadPropertyChildNodes(DbControl dc, OverviewContext context, Node bioAssayNode)
    158159  {
    159     getNodeLoader(context, Item.EXTRACT).createReverseNode(dc, context, bioAssayNode);
     160    Extract e = getExtract((DerivedBioAssay)bioAssayNode.getItem());
     161    if (e == null || bioAssayNode.getFirstParent(new BasicItemFilter(e)) == null)
     162    {
     163      // Only load the extract if it is not already a parent node
     164      getNodeLoader(context, Item.EXTRACT).createReverseNode(dc, context, bioAssayNode);
     165    }
    160166    getNodeLoader(context, Item.ANNOTATION).createPropertyNode(dc, context, bioAssayNode);
    161167    getNodeLoader(context, Item.FILESETMEMBER).createPropertyNode(dc, context, bioAssayNode);
     
    281287    NodeFactory<DerivedBioAssay> nf = getNodeFactory(dc, context);
    282288    Node folderNode = null;
     289    // Load derived bioassays linked to the 'extract' if:
     290    // they have no parent bioassay OR
     291    // the parent bioassay has no parent extract OR
     292    // the parent bioassay has a different parent extract
    283293    ItemQuery<DerivedBioAssay> query = DerivedBioAssay.getQuery();
    284294    query.restrict(Restrictions.eq(Hql.property("extract"), Hql.entity(extract)));
    285295    query.join(Hql.leftJoin("parents", "parent"));
    286     query.restrict(Restrictions.eq(Hql.alias("parent"), null));
     296    query.join(Hql.leftJoin("parent", "extract", "parentExtract", null, false));
     297    query.restrict(
     298      Restrictions.or(
     299        Restrictions.eq(Hql.alias("parent"), null),
     300        Restrictions.eq(Hql.alias("parentExtract"), null),
     301        Restrictions.neq(Hql.alias("parentExtract"), Hql.entity(extract))
     302        ));
     303    query.setDistinct(true); // left joins may create multiple hits for items with more than one parent
    287304    context.initQuery(query, "name");
    288305    ItemResultIterator<DerivedBioAssay> it = query.iterate(dc);
  • trunk/src/core/net/sf/basedb/util/overview/loader/RawBioAssayLoader.java

    r7303 r7494  
    4747import net.sf.basedb.util.overview.NodeAttribute;
    4848import net.sf.basedb.util.overview.OverviewContext;
     49import net.sf.basedb.util.overview.filter.BasicItemFilter;
    4950import net.sf.basedb.util.overview.filter.ItemTypeFilter;
    5051import net.sf.basedb.util.overview.node.ChildNodeDirection;
     
    169170  protected void loadPropertyChildNodes(DbControl dc, OverviewContext context, Node rawBioAssayNode)
    170171  {
    171     getNodeLoader(context, Item.EXTRACT).createReverseNode(dc, context, rawBioAssayNode);
     172    Extract e = getExtract((RawBioAssay)rawBioAssayNode.getItem());
     173    if (e == null || rawBioAssayNode.getFirstParent(new BasicItemFilter(e)) == null)
     174    {
     175      // Only load the extract if it is not already a parent node
     176      getNodeLoader(context, Item.EXTRACT).createReverseNode(dc, context, rawBioAssayNode);
     177    }
    172178    getNodeLoader(context, Item.ANNOTATION).createPropertyNode(dc, context, rawBioAssayNode);
    173179    getNodeLoader(context, Item.FILESETMEMBER).createPropertyNode(dc, context, rawBioAssayNode);
     
    235241    NodeFactory<RawBioAssay> nf = getNodeFactory(dc, context);
    236242    Node folderNode = null;
     243    // Load raw bioassays linked to the 'extract' if:
     244    // they have no parent bioassay OR
     245    // the parent bioassay has no parent extract OR
     246    // the parent bioassay has a different parent extract
    237247    ItemQuery<RawBioAssay> query = RawBioAssay.getQuery();
    238248    query.restrict(Restrictions.eq(Hql.property("parentExtract"), Hql.entity(extract)));
    239     query.restrict(Restrictions.eq(Hql.property("parentBioAssay"), null));
     249    query.join(Hql.leftJoin("parentBioAssay", "parent"));
     250    query.join(Hql.leftJoin("parent", "extract", "parentExtract", null, false));
     251    query.restrict(
     252        Restrictions.or(
     253          Restrictions.eq(Hql.alias("parent"), null),
     254          Restrictions.eq(Hql.alias("parentExtract"), null),
     255          Restrictions.neq(Hql.alias("parentExtract"), Hql.entity(extract))
     256          ));
    240257    context.initQuery(query, "name");
    241258    ItemResultIterator<RawBioAssay> it = query.iterate(dc);
     
    253270  }
    254271 
     272  /**
     273    Get the extract that is associated with the current raw bioassay
     274    @return The extract or null if none was found
     275  */
     276  private Extract getExtract(RawBioAssay bioAssay)
     277  {
     278    Extract extract = null;
     279    try
     280    {
     281      extract = bioAssay.getParentExtract();
     282    }
     283    catch (PermissionDeniedException ex)
     284    {}
     285    return extract;
     286  }
     287
    255288  private Set<Integer> getExtractChain(DbControl dc, Node node)
    256289  {
  • trunk/www/common/import/index.jsp

    r7201 r7494  
    189189
    190190    cc.setObject("auto-detected-file", f);
     191    cc.setObject("last-file-charset", charset);
    191192    int matches = plugins.size();
    192193    if (matches == 0)
  • trunk/www/common/plugin/configure.jsp

    r7030 r7494  
    9999    }
    100100  }
     101 
     102  // Special handling for "charset" parameter to make it match the auto-selected file
     103  if (currentContext != null && Parameters.CHARSET_PARAMETER.equals(pp.getName()))
     104  {
     105    Object charset = currentContext.getObject("last-file-charset");
     106    if (charset != null) values = Collections.singletonList(charset);
     107  }
     108 
    101109  // Then, we check the parameters default value
    102110  if ((values == null || values.size() == 0) && pp.getDefaultValue() != null)
     
    123131        try
    124132        {
    125           values.add(File.getById(dc, cc.getId()).getPath().toString());
     133          File file = File.getById(dc, cc.getId());
     134          values.add(file.getPath().toString());
     135          if (currentContext != null && file.getCharacterSet() != null)
     136          {
     137            currentContext.setObject("last-file-charset", file.getCharacterSet());
     138          }
    126139        }
    127140        catch (Throwable t)
  • trunk/www/common/plugin/parse_file.jsp

    r6684 r7494  
    2424  @version 2.0
    2525--%>
    26 <%@page import="org.json.simple.JSONObject"%>
    2726<%@ page pageEncoding="UTF-8" session="false"
    2827  contentType="text/html; charset=UTF-8" 
     
    4948  import="java.io.InputStream"
    5049  import="org.json.simple.JSONArray"
     50  import="org.json.simple.JSONObject"
    5151%>
    5252<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
     
    173173  %>
    174174  <base:page type="iframe" title="Test with file">
    175   <base:head scripts="tabcontrol-2.js,~parse_file.js" styles="table.css,tabcontrol.css" />
     175  <base:head scripts="tabcontrol-2.js,~parse_file.js" styles="table.css,tabcontrol.css">
     176    <style>
     177    #fileData td
     178    {
     179      white-space: nowrap;
     180      max-width: 20em;
     181      min-width: 4em;
     182      overflow: hidden;
     183      text-overflow: ellipsis;
     184    }
     185    #fileData td:first-child
     186    {
     187      font-weight: bold;
     188    }
     189    .skipped
     190    {
     191      padding: 1px 2px 1px 2px;
     192      color: #777777;
     193      font-style: italic;
     194    }
     195    </style>
     196  </base:head>
    176197  <base:body>
    177198  <div class="absolutefull bottomborder">
     
    216237      <div class="itemlist" style="<%=messages.size()==0 ? "" : "border-top-width: 1px;"%>">
    217238        <div class="data">
    218         <table style="border: 0;">
     239        <table style="border: 0;" id="fileData">
    219240          <thead class="bg-filled-100">
    220241          <tr>
     
    234255        int rowClassIndex = 0;
    235256
    236         while (currentLine <= maxLines && currentLine < headerLines)
     257        while (currentLine < maxLines && currentLine < headerLines)
    237258        {
    238259          FlatFileParser.Line line = parser.getLine(currentLine);
    239260          linePatterns.add(Pattern.quote(line.line()));
    240261          String[] data = null;
     262          int numMoreColumns = 0;
    241263          if (line.type() == FlatFileParser.LineType.HEADER)
    242264          {
     
    246268          {
    247269            data = parser.trimQuotes(splitter.split(line.line(), 99));
     270            if (data.length == 99)
     271            {
     272              numMoreColumns = splitter.split(line.line()).length - 99;
     273            }
    248274          }
    249275          else
     
    254280          <tr class="<%=rowclass[rowClassIndex]%> highlight">
    255281            <td class="cell"><%=line.lineNo()%></td>
    256             <td class="cell"><%=data.length%></td>
     282            <td class="cell"><%=data.length+numMoreColumns%></td>
    257283            <td class="cell"><%=line.type()%></td>
    258284            <td class="cell">
     
    290316        {
    291317          if (lastLine == FlatFileParser.LineType.DATA) parser.nextData();
    292           while (currentLine <= maxLines && parser.hasMoreData())
     318          while (currentLine < maxLines && parser.hasMoreData())
    293319          {
    294320            FlatFileParser.Data data = parser.nextData();
     
    298324              %>
    299325              <tr>
    300                 <td class="error" colspan="103">
     326                <td class="skipped bg-filled-100" colspan="103">
    301327                Skipped <%=parser.getNumSkippedLines()%> lines
    302328                (<%=parser.getIgnoredLines()%> ignored; <%=parser.getUnknownLines()%> unknown)
     
    320346              </td>
    321347              <%
    322               for (int i = 0; i < data.columns(); ++i)
     348              for (int i = 0; i < data.columns() && i < 99; ++i)
    323349              {
    324350                %>
  • trunk/www/include/scripts/main-2.js

    r7447 r7494  
    45514551      optionDiv.optionIndex = i;
    45524552      optionDiv.innerHTML = options[i];
    4553       options[i].div = optionDiv;
    45544553      mainDiv.appendChild(optionDiv);
    45554554    }
Note: See TracChangeset for help on using the changeset viewer.