/**
  * Only true if something changes the status of, or information about, the attendee.
  *
  * @param val
  * @param checkPartStat - true if we check the partstat
  * @return true for significant change
  */
 public boolean changedBy(final BwAttendee val, final boolean checkPartStat) {
   return ((checkPartStat && (Util.compareStrings(val.getPartstat(), getPartstat()) != 0)))
       || (Util.compareStrings(val.getCn(), getCn()) != 0)
       || (Util.compareStrings(val.getCuType(), getCuType()) != 0)
       || (Util.compareStrings(val.getDelegatedFrom(), getDelegatedFrom()) != 0)
       || (Util.compareStrings(val.getDelegatedTo(), getDelegatedTo()) != 0)
       || (Util.compareStrings(val.getDir(), getDir()) != 0)
       || (Util.compareStrings(val.getLanguage(), getLanguage()) != 0)
       || (Util.compareStrings(val.getMember(), getMember()) != 0)
       || (Util.compareStrings(val.getRole(), getRole()) != 0)
       || (Util.compareStrings(val.getSentBy(), getSentBy()) != 0)
       || (Util.compareStrings(val.getAttendeeUri(), getAttendeeUri()) != 0);
 }
 public boolean differsFrom(final BwAttendee val) {
   return (Util.compareStrings(val.getPartstat(), getPartstat()) != 0)
       || (Util.compareStrings(val.getCn(), getCn()) != 0)
       || (Util.compareStrings(val.getCuType(), getCuType()) != 0)
       || (Util.compareStrings(val.getDelegatedFrom(), getDelegatedFrom()) != 0)
       || (Util.compareStrings(val.getDelegatedTo(), getDelegatedTo()) != 0)
       || (Util.compareStrings(val.getDir(), getDir()) != 0)
       || (Util.compareStrings(val.getLanguage(), getLanguage()) != 0)
       || (Util.compareStrings(val.getMember(), getMember()) != 0)
       || (Util.cmpBoolval(val.getRsvp(), getRsvp()) != 0)
       || (Util.compareStrings(val.getRole(), getRole()) != 0)
       || (Util.compareStrings(val.getSentBy(), getSentBy()) != 0)
       || (Util.compareStrings(val.getAttendeeUri(), getAttendeeUri()) != 0)
       || (Util.cmpIntval(val.getScheduleAgent(), getScheduleAgent()) != 0);
 }
  /* Fetch the iCalendar for the subscription. If it fails set the status and
   * return null. Unchanged data will return null with no status change.
   */
  private void getIcal() throws SynchException {
    try {
      if (fetchedIcal != null) {
        return;
      }

      getClient();

      Header[] hdrs = null;

      if ((uidMap != null) && (info.getChangeToken() != null) && (fetchedIcal != null)) {
        hdrs = new Header[] {new BasicHeader("If-None-Match", info.getChangeToken())};
      }

      int rc = client.sendRequest("GET", info.getUri(), hdrs);
      info.setLastRefreshStatus(String.valueOf(rc));

      if (rc == HttpServletResponse.SC_NOT_MODIFIED) {
        // Data unchanged.
        if (debug) {
          trace("data unchanged");
        }
        return;
      }

      if (rc != HttpServletResponse.SC_OK) {
        info.setLastRefreshStatus(String.valueOf(rc));
        if (debug) {
          trace("Unsuccessful response from server was " + rc);
        }
        info.setChangeToken(null); // Force refresh next time
        return;
      }

      CalendarBuilder builder = new CalendarBuilder();

      InputStream is = client.getResponse().getContentStream();

      Calendar ical = builder.build(is);

      /* Convert each entity to XML */

      fetchedIcal = IcalToXcal.fromIcal(ical, null);

      uidMap = new HashMap<String, MapEntry>();

      prodid = null;

      for (VcalendarType vcal : fetchedIcal.getVcalendar()) {
        /* Extract the prodid from the converted calendar - we use it when we
         * generate a new icalendar for each entity.
         */
        if ((prodid == null) && (vcal.getProperties() != null)) {
          for (JAXBElement<? extends BasePropertyType> pel :
              vcal.getProperties().getBasePropertyOrTzid()) {
            if (pel.getValue() instanceof ProdidPropType) {
              prodid = ((ProdidPropType) pel.getValue()).getText();
              break;
            }
          }
        }

        for (JAXBElement<? extends BaseComponentType> comp :
            vcal.getComponents().getBaseComponent()) {
          UidPropType uidProp = (UidPropType) XcalUtil.findProperty(comp.getValue(), XcalTags.uid);

          if (uidProp == null) {
            // Should flag as an error
            continue;
          }

          String uid = uidProp.getText();

          MapEntry me = uidMap.get(uid);

          if (me == null) {
            me = new MapEntry();
            me.uid = uid;
            uidMap.put(uidProp.getText(), me);
          }

          LastModifiedPropType lm =
              (LastModifiedPropType) XcalUtil.findProperty(comp.getValue(), XcalTags.lastModified);

          String lastmod = null;
          if (lm != null) {
            lastmod = lm.getUtcDateTime().toXMLFormat();
          }

          if (Util.cmpObjval(me.lastMod, lastmod) < 0) {
            me.lastMod = lastmod;
          }

          me.comps.add(comp);
        }
      }

      /* Looks like we translated ok. Save any etag and delete everything in the
       * calendar.
       */

      String etag = client.getResponse().getResponseHeaderValue("Etag");
      if (etag != null) {
        info.setChangeToken(etag);
      }
    } catch (SynchException se) {
      throw se;
    } catch (Throwable t) {
      throw new SynchException(t);
    } finally {
      try {
        client.release();
      } catch (Throwable t) {
      }
    }
  }