public TrialDataImportResult importTrialData(Long editTrialDataID, InputStream is)
      throws ExcelImportExportException {

    // map to collect invalid date values. this map allows further
    // processing
    // (not implemented atm)
    Map<Value, Serializable> invalidDateValues = new HashMap<Value, Serializable>();

    // map to store the values from the xls
    Map<String, Serializable> valueMap = null;

    int importCnt = 0;

    TrialData trialData = trialDataDAO.findByID(editTrialDataID);

    valueMap = excelReader.readXLSX(is);

    log.info("sucessfully loaded data from excel sheet");

    for (AttributeGroup aGroup : trialData.getTrialform().getAttributeGroups()) {

      for (Attribute attr : aGroup.getAttributes()) {

        // search attribute in map
        Serializable mapVal = valueMap.get(attr.getName());

        if (mapVal == null) continue;

        importCnt++;

        Value value = valueFactory.getValueObject(attr.getFormElement().getDataType());

        try {
          value.setValueObject(mapVal);
        } catch (IllegalArgumentException e) {
          if (value.getType() == DATATYPE.DATE) {
            invalidDateValues.put(value, mapVal);
          }
        }

        value.setAttribute(attr);
        value.setTrialData(trialData);

        trialData.getValues().add(value);
        valueDAO.persist(value);
      }
    }

    TrialDataImportResult result = new TrialDataImportResult();
    result.setImportCnt(importCnt);
    result.setSuccCnt(valueMap.keySet().size());
    result.setTrialData(trialData);

    return result;
  }
  public String undo(ValueEvent ve) {
    List<ValueEvent> newer = eventDAO.getNewerEvents(ve);
    Collections.sort(newer);

    if (stillExists(newer)) {
      Value v = valueDAO.findByID(new Value.ValueId(ve.getAttributeId(), ve.getTrialdataId()));

      if (ve instanceof ValueCreateEvent) {
        log.debug("Removing Value #0/#1", v.getId().getAttributeId(), v.getId().getTrialDataId());
        valueDAO.remove(v);
      } else {
        log.debug(
            "reversing value of #0/#1 to #2",
            v.getId().getAttributeId(),
            v.getId().getTrialDataId(),
            ve.getOldValue());
        v.setValueObject(ve.getOldValue());
      }
    } else {

      if (!(ve instanceof ValueCreateEvent)) {
        log.debug(
            "restoring value #0/#1 with value #2",
            ve.getAttributeId(),
            ve.getTrialdataId(),
            ve.getOldValue());
        Attribute a = attributeDAO.findByID(ve.getAttributeId());
        if (a == null)
          throw new IllegalArgumentException(
              "Could not restore value, attribute has been removed!");

        Value v = valueFactory.getValueObject(a.getFormElement().getDataType());
        v.setAttribute(a);
        TrialData td = new TrialData();
        td.setId(ve.getTrialdataId());
        v.setTrialData(td);
        v.setValueObject(ve.getOldValue());

        valueDAO.persist(v);
      }
    }

    // remove all newer Events
    for (ValueEvent ve1 : newer) {
      eventDAO.remove(ve1);
    }

    // reset datamodel
    changes = null;

    return null;
  }