protected void updateAttributeValueProperties(Site site, PropertyMap changes, boolean creating) {

    Map<Integer, Boolean> attributeValues = new HashMap<Integer, Boolean>();

    for (Map.Entry<String, Object> change : changes.entrySet()) {
      if (change.getKey().startsWith(AttributeDTO.PROPERTY_PREFIX)) {
        attributeValues.put(
            AttributeDTO.idForPropertyName(change.getKey()), (Boolean) change.getValue());
      }
    }
    if (!attributeValues.isEmpty()) {
      siteDAO.updateAttributeValues(site.getId(), attributeValues);
    }
  }
  public void update(User user, Object id, PropertyMap changes) {

    Site site = siteDAO.findById((Integer) id);

    assertSiteEditPrivileges(user, site.getDatabase(), site.getPartner());

    site.setDateEdited(new Date());

    updateSiteProperties(site, changes, false);
    updateAttributeValueProperties(site, changes, false);
    updateLocationProperties(site.getLocation(), changes);
    updateAdminProperties(site.getLocation(), changes, false);

    if (!site.getReportingPeriods().isEmpty()) {
      ReportingPeriod period = site.getReportingPeriods().iterator().next();
      updatePeriodProperties(period, changes, false);
      updateIndicatorValueProperties(period, changes, false);
    }
  }
  protected void updateSiteProperties(Site site, PropertyMap changes, boolean creating) {

    for (Map.Entry<String, Object> change : changes.entrySet()) {

      String property = change.getKey();
      Object value = change.getValue();

      if ("date1".equals(property)) {
        site.setDate1((Date) value);

      } else if ("date2".equals(property)) {
        site.setDate2((Date) value);

      } else if ("assessmentId".equals(property)) {
        site.setAssessment(siteDAO.findById((Integer) value));

      } else if ("comments".equals(property)) {
        site.setComments((String) value);

      } else if ("status".equals(property)) {
        site.setStatus((Integer) value);
      }
    }
  }
  @Override
  public Integer create(User user, PropertyMap properties) {

    Activity activity = null;
    UserDatabase database;
    LocationType locationType;
    OrgUnit partner = null;

    if (properties.containsKey("activityId")) {
      activity = activityDAO.findById((Integer) properties.get("activityId"));
      locationType = activity.getLocationType();
      database = activity.getDatabase();

    } else if (properties.containsKey("databaseId")) {
      database = userDatabaseDAO.findById((Integer) properties.get("databaseId"));
      Set<LocationType> locationTypes = database.getCountry().getLocationTypes();
      if (locationTypes.isEmpty()) {
        throw new RuntimeException(
            "A site cannot be created without a location type, and the country '"
                + database.getCountry().getName()
                + "' (id = "
                + database.getCountry().getId()
                + ") has no location types defined.");
      }
      locationType = locationTypes.iterator().next();
      if (user.getOrganization() != null) {
        partner = user.getOrganization().getRoot();
      }
    } else {
      throw new RuntimeException("An activityId or databaseId must be provided to create a site");
    }

    if (properties.containsKey("partner")) {
      partner = partnerDAO.findById(((PartnerDTO) properties.get("partner")).getId());
    }

    if (partner == null) {
      throw new RuntimeException("No orgUnit id provided for new site");
    }

    /*
     * Create and save a new Location object in the database
     */

    Location location = new Location();
    location.setLocationType(locationType);
    updateLocationProperties(location, properties);

    locationDAO.persist(location);

    updateAdminProperties(location, properties, true);

    /*
     * Create and persist the Site object
     */

    Site site = new Site();
    site.setLocation(location);
    site.setActivity(activity);
    site.setDatabase(database);
    site.setPartner(partner);
    site.setDateCreated(new Date());

    updateSiteProperties(site, properties, true);

    siteDAO.persist(site);

    updateAttributeValueProperties(site, properties, true);

    /*
     * Create the reporting period object
     * IF this is a report-once activity (punctual)
     *
     * otherwise ReportingPeriods are modeled separately on the client.
     */

    if (activity != null && activity.getReportingFrequency() == ActivityDTO.REPORT_ONCE) {

      ReportingPeriod period = new ReportingPeriod();
      period.setSite(site);
      period.setMonitoring(false);

      updatePeriodProperties(period, properties, true);

      reportingPeriodDAO.persist(period);

      updateIndicatorValueProperties(period, properties, true);
    }

    return site.getId();
  }