private APTaxCalculationInfo addPropertyInfo(final Property property) {
   final APTaxCalculationInfo taxCalculationInfo = new APTaxCalculationInfo();
   // Add Property Info
   taxCalculationInfo.setPropertyOwnerName(property.getBasicProperty().getFullOwnerName());
   taxCalculationInfo.setPropertyAddress(property.getBasicProperty().getAddress().toString());
   taxCalculationInfo.setHouseNumber(property.getBasicProperty().getAddress().getHouseNoBldgApt());
   taxCalculationInfo.setZone(property.getBasicProperty().getPropertyID().getZone().getName());
   taxCalculationInfo.setWard(property.getBasicProperty().getPropertyID().getWard().getName());
   taxCalculationInfo.setBlock(property.getBasicProperty().getPropertyID().getArea().getName());
   taxCalculationInfo.setLocality(
       property.getBasicProperty().getPropertyID().getLocality().getName());
   if (property.getPropertyDetail().getSitalArea().getArea() != null)
     if (property
         .getPropertyDetail()
         .getPropertyTypeMaster()
         .getCode()
         .equals(OWNERSHIP_TYPE_VAC_LAND))
       taxCalculationInfo.setPropertyArea(
           convertYardToSquareMeters(property.getPropertyDetail().getSitalArea().getArea()));
     else
       taxCalculationInfo.setPropertyArea(
           new BigDecimal(property.getPropertyDetail().getSitalArea().getArea().toString()));
   taxCalculationInfo.setPropertyType(
       property.getPropertyDetail().getPropertyTypeMaster().getType());
   taxCalculationInfo.setPropertyId(property.getBasicProperty().getUpicNo());
   return taxCalculationInfo;
 }
  /**
   * @param property Property Object
   * @param applicableTaxes List of Applicable Taxes
   * @param occupationDate Minimum Occupancy Date among all the units
   * @return
   */
  @Override
  public HashMap<Installment, TaxCalculationInfo> calculatePropertyTax(
      final Property property, final Date occupationDate) {

    Boundary propertyZone = null;
    BigDecimal totalNetArv = BigDecimal.ZERO;
    BoundaryCategory boundaryCategory = null;
    // TODO move method prepareApplicableTaxes to tax calculator
    final List<String> applicableTaxes = prepareApplicableTaxes(property);
    final List<Installment> taxInstallments = getInstallmentListByStartDate(occupationDate);
    propertyZone = property.getBasicProperty().getPropertyID().getZone();

    for (final Installment installment : taxInstallments) {
      totalTaxPayable = BigDecimal.ZERO;
      final APTaxCalculationInfo taxCalculationInfo = addPropertyInfo(property);

      if (betweenOrBefore(occupationDate, installment.getFromDate(), installment.getToDate())) {
        if (property
            .getPropertyDetail()
            .getPropertyTypeMaster()
            .getCode()
            .equals(OWNERSHIP_TYPE_VAC_LAND)) {
          final APUnitTaxCalculationInfo unitTaxCalculationInfo =
              calculateVacantLandTax(property, occupationDate);
          totalNetArv = totalNetArv.add(unitTaxCalculationInfo.getNetARV());
          taxCalculationInfo.addUnitTaxCalculationInfo(unitTaxCalculationInfo);
          calculateApplicableTaxes(
              applicableTaxes,
              unitTaxCalculationInfo,
              installment,
              property.getPropertyDetail().getPropertyTypeMaster().getCode());
          totalTaxPayable = totalTaxPayable.add(unitTaxCalculationInfo.getTotalTaxPayable());
        } else
          for (final Floor floorIF : property.getPropertyDetail().getFloorDetails())
            if (floorIF != null) {
              // TODO think about, these beans to be client
              // specific
              boundaryCategory =
                  getBoundaryCategory(
                      propertyZone,
                      installment,
                      floorIF.getPropertyUsage().getId(),
                      occupationDate);
              final APUnitTaxCalculationInfo unitTaxCalculationInfo =
                  prepareUnitCalcInfo(property, floorIF, boundaryCategory);
              totalNetArv = totalNetArv.add(unitTaxCalculationInfo.getNetARV());

              calculateApplicableTaxes(
                  applicableTaxes,
                  unitTaxCalculationInfo,
                  installment,
                  property.getPropertyDetail().getPropertyTypeMaster().getCode());

              totalTaxPayable = totalTaxPayable.add(unitTaxCalculationInfo.getTotalTaxPayable());
              taxCalculationInfo.addUnitTaxCalculationInfo(unitTaxCalculationInfo);
            }
        taxCalculationInfo.setTotalNetARV(totalNetArv);
        taxCalculationInfo.setTotalTaxPayable(totalTaxPayable);
        taxCalculationInfo.setTaxCalculationInfoXML(generateTaxCalculationXML(taxCalculationInfo));
        taxCalculationMap.put(installment, taxCalculationInfo);
      }
    }
    return taxCalculationMap;
  }