private long parseLine(String line) throws DaoException {
    CouchChange changes = JSONParser.defaultJSONParser().parse(CouchChange.class, line);
    Document document = changes.getDoc();

    if (changes.getLast_seq() != null)
      Log.debug("StatisticAggregator got changes line: '" + line + "'");

    if (changes.getDeleted() == true) {
      _statisticDao.delete(_statisticDao.getAffectedIDs(changes.getId()));
    } else if (document != null && document.getDocTypeEnum() != null) {
      switch (document.getDocTypeEnum()) {
        case RECEIPT:
          receiptChanged(changes);
          break;
        case PACKAGE:
        case PRODUCT:
        case SHOP:
          documentChanged(changes);
          break;
      }
    }
    return changes.getSeq();
  }
  private void receiptChanged(CouchChange changes) throws DaoException {
    Document document = changes.getDoc();

    // first delete all the old statistics documents that are associated to this Receipt
    _statisticDao.delete(_statisticDao.getIDsByReceipt(document.getId()));

    // then create a new one for each receipt entry
    Shop shop = null;
    Date timestamp = null;
    Category shopCategory = null;

    if (document.hasProperty("shopId")) {
      String shopId = document.getProperty("shopId").toString();
      if (shopId != null) {
        Shop originalShop = _shopDao.get(document.getProperty("shopId").toString());
        shop = new Shop(null, originalShop.getId(), null, originalShop.getTitle(), null);
        if (originalShop.getAddress() != null && originalShop.getAddress().getPos() != null) {
          LatLon pos = originalShop.getAddress().getPos();
          shop.setAddress(new Address(null, null, null, null, pos.getLat(), pos.getLon()));
        }
        if (originalShop.getCategoryId() != null) {
          shopCategory =
              new Category(
                  null,
                  originalShop.getCategoryId(),
                  null,
                  originalShop.getCategory().getTitle(),
                  null);
        }
      }
    }

    if (document.hasProperty("timeStamp")) {
      Object timestampObject = document.getProperty("timeStamp");
      Long timestampLong = null;
      if (timestampObject instanceof BigDecimal) {
        timestampLong = ((BigDecimal) timestampObject).longValue();
      } else {
        timestampLong = new Long(timestampObject.toString());
      }

      if (timestampLong != null) timestamp = new Date(timestampLong);
    }

    if (document.hasProperty("receiptEntries")) {
      Object entriesObject = document.getProperty("receiptEntries");
      if (entriesObject instanceof List<?>) {
        List<?> entries = (List<?>) entriesObject;
        for (Object entryObject : entries) {
          if (entryObject instanceof Map<?, ?>) {
            Map<?, ?> entryMap = (Map<?, ?>) entryObject;
            StatisticResult statistic = new StatisticResult();

            statistic.setShop(shop);
            statistic.setShopCategory(shopCategory);
            statistic.setDate(timestamp);
            statistic.setReceiptId(document.getId());
            statistic.setSequenceNr(changes.getSeq());

            // package and product
            if (entryMap.containsKey("packageId")) {
              String packageId = entryMap.get("packageId").toString();
              Package pkg = _packageDao.get(packageId);
              Product product = _productDao.get(pkg.getProductId());
              statistic.setPackage(
                  new Package(
                      null,
                      pkg.getId(),
                      null,
                      new Quantity(pkg.getQuantity().getQuantity(), null)));
              if (product != null) {
                statistic.setProduct(
                    new Product(null, product.getId(), null, product.getTitle(), null, null));

                Category category = null;
                if (product.getCategory() != null) {
                  category =
                      new Category(
                          null,
                          product.getCategoryId(),
                          null,
                          product.getCategory().getTitle(),
                          null);
                  statistic.setProductCategory(category);
                }
              }
              String unitId = pkg.getQuantity().getUnitId();
              if (unitId != null) {
                Unit unit = _unitDao.get(unitId);
                statistic.setUnit(
                    new Unit(null, unit.getId(), null, unit.getTitle(), null, unit.getFactor()));
                if (unit.getParentId() != null) {
                  unit = _unitDao.get(unit.getParentId());
                  statistic.setParentUnit(
                      new Unit(null, unit.getId(), null, unit.getTitle(), null, 0));
                }
              }
            }

            // price
            if (entryMap.containsKey("price")) {
              Object priceObject = entryMap.get("price");
              if (priceObject instanceof Map<?, ?>) {
                Map<?, ?> priceMap = (Map<?, ?>) priceObject;
                statistic.setPrice(
                    new Price(
                        new BigDecimal(priceMap.get("price").toString()),
                        Currency.valueOf(priceMap.get("currency").toString())));
              }
            }
            String json = JSON.formatJSON(JSON.defaultJSON().forValue(statistic));
            System.err.println("JSON:\n" + json);
            _statisticDao.create(statistic);
          }
        }
      }
    }
  }