protected void notify(final SysEvent.SysCode code, final BwEvent val, final boolean shared)
      throws CalFacadeException {
    try {
      final String note = getChanges(code, val);
      if (note == null) {
        return;
      }

      final boolean indexed = (getSyspars().getTestMode() /* &&
                                       (val.getRecurrenceId() == null)*/);

      postNotification(
          SysEvent.makeEntityUpdateEvent(
              code,
              authenticatedPrincipal(),
              val.getOwnerHref(),
              val.getHref(),
              shared,
              indexed,
              val.getRecurrenceId(),
              note,
              null)); // XXX Emit multiple targeted?
    } catch (NotificationException ne) {
      throw new CalFacadeException(ne);
    }
  }
  protected void notifyDelete(final boolean reallyDelete, final BwEvent val, final boolean shared)
      throws CalFacadeException {
    SysEvent.SysCode code;

    if (reallyDelete) {
      code = SysEvent.SysCode.ENTITY_DELETED;
    } else {
      code = SysEvent.SysCode.ENTITY_TOMBSTONED;
    }
    ;

    String note = getChanges(code, val);
    if (note == null) {
      return;
    }

    try {
      postNotification(
          SysEvent.makeEntityDeletedEvent(
              code,
              authenticatedPrincipal(),
              val.getOwnerHref(),
              val.getHref(),
              shared,
              val.getPublick(),
              true, // indexed,
              IcalDefs.fromEntityType(val.getEntityType()),
              val.getRecurrenceId(),
              note,
              null)); // XXX Emit multiple targted?
    } catch (NotificationException ne) {
      throw new CalFacadeException(ne);
    }
  }
  protected void unindexEntity(final EventInfo ei) throws CalFacadeException {
    final BwEvent ev = ei.getEvent();

    if (ev.getRecurrenceId() != null) {
      // Cannot index single instance
      warn("Tried to unindex a recurrence instance");
      return;
    }

    getIndexer(ev).unindexEntity(ev.getHref());
  }
 protected void notifyMove(
     final SysEvent.SysCode code,
     final String oldHref,
     final boolean oldShared,
     final BwEvent val,
     final boolean shared)
     throws CalFacadeException {
   try {
     postNotification(
         SysEvent.makeEntityMovedEvent(
             code,
             currentPrincipal(),
             val.getOwnerHref(),
             val.getHref(),
             shared,
             false,
             oldHref,
             oldShared));
   } catch (NotificationException ne) {
     throw new CalFacadeException(ne);
   }
 }
  protected void notifyInstanceChange(
      final SysEvent.SysCode code,
      final BwEvent val,
      final boolean shared,
      final String recurrenceId)
      throws CalFacadeException {
    try {
      String note = getChanges(code, val);
      if (note == null) {
        return;
      }

      /* We flag these as indexed. They get handled by the update for
        the master
      */
      if (code.equals(SysEvent.SysCode.ENTITY_DELETED)
          || code.equals(SysEvent.SysCode.ENTITY_TOMBSTONED)) {
        postNotification(
            SysEvent.makeEntityDeletedEvent(
                code,
                authenticatedPrincipal(),
                val.getOwnerHref(),
                val.getHref(),
                shared,
                val.getPublick(),
                true, // Indexed
                IcalDefs.fromEntityType(val.getEntityType()),
                recurrenceId,
                note,
                null)); // XXX Emit multiple targted?
      } else {
        postNotification(
            SysEvent.makeEntityUpdateEvent(
                code,
                authenticatedPrincipal(),
                val.getOwnerHref(),
                val.getHref(),
                shared,
                true, // Indexed
                val.getRecurrenceId(),
                note, // changes
                null)); // XXX Emit multiple targted?
      }
    } catch (NotificationException ne) {
      throw new CalFacadeException(ne);
    }
  }
  /**
   * @param val
   * @return VFreeBusy
   * @throws CalFacadeException
   */
  public static VFreeBusy toVFreeBusy(final BwEvent val) throws CalFacadeException {
    try {
      VFreeBusy vfb =
          new VFreeBusy(
              IcalUtil.makeDateTime(val.getDtstart()), IcalUtil.makeDateTime(val.getDtend()));

      PropertyList pl = vfb.getProperties();
      Property prop;

      /* ------------------- Attendees -------------------- */
      if (val.getNumAttendees() > 0) {
        for (BwAttendee att : val.getAttendees()) {
          pl.add(setAttendee(att));
        }
      }

      /* ------------------- Comments -------------------- */

      if (val.getNumComments() > 0) {
        for (BwString str : val.getComments()) {
          // LANG
          pl.add(new Comment(str.getValue()));
        }
      }

      /* ------------------- Dtstamp -------------------- */

      if (val.getDtstamp() != null) {
        DtStamp dts = (DtStamp) pl.getProperty(Property.DTSTAMP);

        if (dts == null) {
          prop = new DtStamp(new DateTime(val.getDtstamp()));
          //      if (pars.includeDateTimeProperty) {
          //      prop.getParameters().add(Value.DATE_TIME);
          //      }
          pl.add(prop);
        } else {
          dts.setDateTime(new DateTime(val.getDtstamp()));
        }
      }

      /* ------------------- freebusy -------------------- */

      Collection<BwFreeBusyComponent> times = val.getFreeBusyPeriods();

      if (times != null) {
        for (BwFreeBusyComponent fbc : times) {
          FreeBusy fb = new FreeBusy();

          int type = fbc.getType();
          if (type == BwFreeBusyComponent.typeBusy) {
            addParameter(fb, FbType.BUSY);
          } else if (type == BwFreeBusyComponent.typeFree) {
            addParameter(fb, FbType.FREE);
          } else if (type == BwFreeBusyComponent.typeBusyUnavailable) {
            addParameter(fb, FbType.BUSY_UNAVAILABLE);
          } else if (type == BwFreeBusyComponent.typeBusyTentative) {
            addParameter(fb, FbType.BUSY_TENTATIVE);
          } else {
            throw new CalFacadeException("Bad free-busy type " + type);
          }

          PeriodList pdl = fb.getPeriods();

          for (Period p : fbc.getPeriods()) {
            // XXX inverse.ca plugin cannot handle durations.
            Period np = new Period(p.getStart(), p.getEnd());
            pdl.add(np);
          }

          pl.add(fb);
        }
      }

      /* ------------------- Organizer -------------------- */

      BwOrganizer org = val.getOrganizer();
      if (org != null) {
        pl.add(setOrganizer(org));
      }

      /* ------------------- Uid -------------------- */

      if (val.getUid() != null) {
        pl.add(new Uid(val.getUid()));
      }

      return vfb;
    } catch (CalFacadeException cfe) {
      throw cfe;
    } catch (Throwable t) {
      throw new CalFacadeException(t);
    }
  }