Changeset 4822


Ignore:
Timestamp:
Mar 19, 2009, 2:06:45 PM (13 years ago)
Author:
Nicklas Nordborg
Message:

Fixes #1255: Make annotation importer handle units

Location:
trunk/src
Files:
5 edited

Legend:

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

    r4743 r4822  
    420420    {
    421421      converter = getUnitConverter(unit);
    422       if (converter != null && value instanceof Number)
     422      Type valueType = getValueType();
     423      if (value instanceof Number)
    423424      {
    424         value = converter.convertToReferenceUnit(((Number)value).doubleValue());
     425        Number numericValue = (Number)value;
     426        if (converter != null)
     427        {
     428          numericValue = converter.convertToReferenceUnit(numericValue.doubleValue());
     429        }
     430        value = valueType.convertNumber(numericValue);
    425431      }
    426432    }
     
    472478    for (Object value : values)
    473479    {
    474       if (converter != null && value instanceof Number)
     480      if (value instanceof Number)
    475481      {
    476         value = valueType.convertNumber(converter.convertToReferenceUnit(((Number)value).doubleValue()));
     482        Number numericValue = (Number)value;
     483        if (converter != null)
     484        {
     485          numericValue = converter.convertToReferenceUnit(numericValue.doubleValue());
     486        }
     487        value = valueType.convertNumber(numericValue);
    477488      }
    478489      annotationType.validateAnnotationValue(value);
  • trunk/src/core/net/sf/basedb/core/AnnotationType.java

    r4696 r4822  
    12331233 
    12341234  /**
    1235     Validate an annotation value. We check the following:
     1235    Validate an annotation value assuming that the value
     1236    is in the default unit.
     1237    @param value The object to be validated
     1238    @throws InvalidDataException If the value object can not be used.
     1239    @see #validateAnnotationValue(Object, Unit)
     1240    @see #getDefaultUnit()
     1241  */
     1242  public void validateAnnotationValue(Object value)
     1243    throws InvalidDataException
     1244  {
     1245    validateAnnotationValue(value, null);
     1246  }
     1247 
     1248  /**
     1249    Validate an annotation value that can be in a different unit than
     1250    the default unit. We check the following:
    12361251    <ul>
    1237     <li>The object is of the correct type, ie. <code>Float</code> if {@link #getValueType()}
    1238       returns {@link Type#FLOAT}, etc.
     1252    <li>The object is of the correct type, ie. <code>Float</code>
     1253      if {@link #getValueType()} returns {@link Type#FLOAT}, etc.
     1254      NOTE! If a unit is specified it is only required that the
     1255      value is a {@link Number}. It will automatically be converted
     1256      to the correct class after unit conversion has taken place.
    12391257    <li>The value is within the min and max bouds if specified
    12401258    <li>A string value is not too long
     
    12431261    </ul>
    12441262    @param value The object to be validated
     1263    @param unit The unit if the value, this parameter is ignored if
     1264      the value type doesn't support units (eg. strings) or if the
     1265      no default unit has been set for this annotation type
     1266    @return The validated value which may have been converted to the
     1267      default unit
    12451268    @throws InvalidDataException If the value object can not be used.
    1246   */
    1247   public void validateAnnotationValue(Object value)
     1269    @since 2.11
     1270  */
     1271  public Object validateAnnotationValue(Object value, Unit unit)
    12481272    throws InvalidDataException
    12491273  {
    12501274    if (value == null) throw new InvalidUseOfNullException("value");
    12511275    Type valueType = getValueType();
     1276   
     1277    if (supportUnits() && unit != null && value instanceof Number)
     1278    {
     1279      Unit defaultUnit = getDefaultUnit();
     1280      value = valueType.convertNumber(
     1281          defaultUnit.fromOther(((Number)value).doubleValue(), unit));
     1282    }
    12521283    valueType.validate(value);
     1284   
    12531285    if (valueType == Type.INT)
    12541286    {
     
    13611393      }
    13621394    }
     1395    return value;
    13631396  }
    13641397 
  • trunk/src/plugins/core/net/sf/basedb/plugins/AnnotationFlatFileImporter.java

    r4669 r4822  
    6464import net.sf.basedb.core.StringTooLongException;
    6565import net.sf.basedb.core.Type;
     66import net.sf.basedb.core.Unit;
    6667import net.sf.basedb.core.Version;
    6768import net.sf.basedb.core.plugin.About;
     
    8889import net.sf.basedb.util.parser.Mapper;
    8990import net.sf.basedb.util.parser.FlatFileParser.Data;
     91import net.sf.basedb.util.units.UnitCache;
     92import net.sf.basedb.util.units.UnitUtil;
    9093
    9194/**
     
    345348      permissions.add(new Permissions(Item.FILE, null, EnumSet.of(Permission.READ)));
    346349      permissions.add(new Permissions(Item.ANNOTATIONTYPE, null, EnumSet.of(Permission.READ)));
    347      
     350      permissions.add(new Permissions(Item.UNIT, EnumSet.of(Permission.READ), null));
     351      permissions.add(new Permissions(Item.QUANTITY, EnumSet.of(Permission.READ), null));
    348352      for (GuiContext ctx : getGuiContexts())
    349353      {
     
    591595  private List<String> columnHeaders;
    592596  private DbControl dc;
     597  private UnitCache unitCache;
    593598  private FlatFileParser ffp;
    594599  private NumberFormat numberFormat;
     
    694699  {
    695700    this.dc = sc.newDbControl();
     701    this.unitCache = new UnitCache(dc);
    696702   
    697703    // Mapper to get name or external ID
     
    786792
    787793        Object annotationValue = null;
     794        Unit unit = null;
     795        Unit defaultUnit = at.getDefaultUnit();
    788796        try
    789797        {
     
    794802            if (enumValue != null) sValue = enumValue;
    795803          }
    796           annotationValue = at.getValueType().parseString(sValue, numberFormat, false);
     804          if (at.supportUnits())
     805          {
     806            // Check if the value is followed by a unit
     807            String[] valueAndUnit = UnitUtil.splitValueWithUnit(sValue);
     808            if (valueAndUnit != null)
     809            {
     810              String unitSymbol = valueAndUnit[1];
     811              if (unitSymbol != null)
     812              {
     813                // Yes.. there is a unit, look it up
     814                unit = unitCache.findUnit(at.getQuantity(), unitSymbol);
     815                if (unit == null)
     816                {
     817                  // The unit doesn't exists
     818                  throw new NumberFormatException("Unknown unit for value: " + sValue);
     819                }
     820              }
     821              else
     822              {
     823                // No unit specified, use the default unit
     824                unit = at.getDefaultUnit();
     825              }
     826              sValue = valueAndUnit[0];
     827            }
     828          }
     829          if (unit != null)
     830          {
     831            annotationValue = Type.DOUBLE.parseString(sValue, numberFormat, false);
     832          }
     833          else
     834          {
     835            annotationValue = at.getValueType().parseString(sValue, numberFormat, false);
     836          }
    797837          if (annotationValue != null)
    798838          {
    799             at.validateAnnotationValue(annotationValue);
     839            at.validateAnnotationValue(annotationValue, unit);
    800840          }
    801841          for (NewAnnotations item : items)
    802842          {
    803843            // Add annotation value to the cache
    804             item.addValue(at, annotationValue);
     844            item.addValue(at, annotationValue, unit);
    805845          }
    806846        }
     
    11771217  }
    11781218 
     1219  private static class AnnotationValue
     1220  {
     1221    final Object value;
     1222    final Unit unit;
     1223    AnnotationValue(Object value, Unit unit)
     1224    {
     1225      this.value = value;
     1226      this.unit = unit;
     1227    }
     1228  }
     1229 
    11791230  /**
    11801231    Internal cache for storing annotation values from the file
     
    11851236  {
    11861237    private final Annotatable item;
    1187     private final Map<AnnotationType, List<Object>> values;
     1238    private final Map<AnnotationType, List<AnnotationValue>> values;
    11881239    private int numAnnotations;
    11891240    private int numSet;
     
    11981249    {
    11991250      this.item = item;
    1200       this.values = new HashMap<AnnotationType, List<Object>>();
     1251      this.values = new HashMap<AnnotationType, List<AnnotationValue>>();
    12011252      this.numAnnotations = 0;
    12021253    }
     
    12061257      error before calling this method.
    12071258    */
    1208     void addValue(AnnotationType at, Object value)
    1209     {
    1210       List<Object> listOfValues = values.get(at);
     1259    void addValue(AnnotationType at, Object value, Unit unit)
     1260    {
     1261      List<AnnotationValue> listOfValues = values.get(at);
    12111262      if (listOfValues == null)
    12121263      {
    1213         listOfValues = new LinkedList<Object>();
     1264        listOfValues = new LinkedList<AnnotationValue>();
    12141265        values.put(at, listOfValues);
    12151266      }
    12161267      if (value != null)
    12171268      {
    1218         listOfValues.add(value);
     1269        listOfValues.add(new AnnotationValue(value, unit));
    12191270        numAnnotations++;
    12201271      }
     
    12441295      int numAnnotations = 0;
    12451296      AnnotationSet as = item.getAnnotationSet();
    1246       for (Map.Entry<AnnotationType, List<Object>> entry : values.entrySet())
     1297      for (Map.Entry<AnnotationType, List<AnnotationValue>> entry : values.entrySet())
    12471298      {
    12481299        AnnotationType at = entry.getKey();
    1249         List<Object> newValues = entry.getValue();
     1300        List<AnnotationValue> newValues = entry.getValue();
    12501301        int size = newValues.size();
    12511302        int multiplicity = at.getMultiplicity();
    12521303        boolean hasAnnotation = as.hasAnnotation(at);
    12531304        boolean merge = addToUnlimited && hasAnnotation && multiplicity == 0;
    1254         boolean tooManyValues = multiplicity > 0 && newValues.size() > multiplicity;
     1305        boolean tooManyValues = multiplicity > 0 && size > multiplicity;
    12551306        if (size == 0)
    12561307        {
     
    12681319            {
    12691320              Annotation a = as.getAnnotation(at);
    1270               if (merge) newValues.addAll(0, a.getValues());
    1271               a.setValues(newValues);
     1321              List<Object> theValues = new ArrayList<Object>(newValues.size());
     1322              // Make sure all annotation values are converted to the same unit
     1323              final Unit unit = merge ? a.getUnit() : newValues.get(0).unit;
     1324              if (merge)
     1325              {
     1326                theValues.addAll(a.getValues(unit));
     1327              }
     1328              for (AnnotationValue value : newValues)
     1329              {
     1330                Object theValue = value.value;
     1331                if (unit != null && !unit.equals(value.unit))
     1332                {
     1333                  theValue = unit.fromOther(((Number)value.value).doubleValue(), value.unit);
     1334                }
     1335                theValues.add(theValue);
     1336              }
     1337              a.setValues(theValues, unit);
    12721338              numSet += size;
    12731339              if (hasAnnotation && !merge) numReplaced += size;
  • trunk/src/test/TestAnnotationFlatFileImporter.java

    r4544 r4822  
    3333import net.sf.basedb.core.PluginParameter;
    3434import net.sf.basedb.core.PluginResponse;
     35import net.sf.basedb.core.Quantity;
    3536import net.sf.basedb.core.RequestInformation;
     37import net.sf.basedb.core.SystemItems;
    3638import net.sf.basedb.core.Type;
    3739import net.sf.basedb.core.plugin.GuiContext;
     
    5658    // Create annotation types, samples and upload file
    5759   
    58     int timeId = TestAnnotationType.test_create("Time (hours)", Type.INT, 0, null, 25, Item.SAMPLE, 1, null, false);
     60    int timeQuantityId = SystemItems.getId(Quantity.TIME);
     61    int hoursId = TestUnit.test_load_by_symbol(timeQuantityId, "h");
     62   
     63    int timeId = TestAnnotationType.test_create("Time (hours)", Type.INT, hoursId, null, 25, Item.SAMPLE, 1, null, false);
    5964    int ageId = TestAnnotationType.test_create("Age (years)", Type.INT, 0, null, 100, Item.SAMPLE, 1, null, false);
    6065    int commentId = TestAnnotationType.test_create("Comment", Type.STRING, 0, null, 20, Item.SAMPLE, 0, null, false);
     
    6974    int sampleDup2 = TestSample.test_create(0, "Sample dup", false);
    7075   
    71     TestAnnotation.test_annotatate(Item.SAMPLE, sample4, timeId, 0, 12);
    7276    TestAnnotation.test_annotatate(Item.SAMPLE, sample4, ageId, 0, 2);
    7377    TestAnnotation.test_annotatate(Item.SAMPLE, sample4, enumId, 0, "gamma");
     
    8791    TestAnnotation.test_list_annotations(Item.SAMPLE, sample2, 2);
    8892    TestAnnotation.test_list_annotations(Item.SAMPLE, sample3, 2);
    89     TestAnnotation.test_list_annotations(Item.SAMPLE, sample4, 1);
     93    TestAnnotation.test_list_annotations(Item.SAMPLE, sample4, 2);
    9094    TestAnnotation.test_list_annotations(Item.SAMPLE, sampleDup1, 4);
    9195    TestAnnotation.test_list_annotations(Item.SAMPLE, sampleDup2, 4);
  • trunk/src/test/data/test.annotation.import.txt

    r4599 r4822  
    1212# Test: item not found
    1313NoSample  0 0 alfa  Good  Very good
    14 # Test: remove annotations; add value to existing
    15 Sample #4         A comment from file
     14# Test: remove annotations; add value to existing; value with unit (120min=2h)
     15Sample #4 120min        A comment from file
Note: See TracChangeset for help on using the changeset viewer.