public Collection<EventBean> getSnapshot(
     EPStatementHandle createWindowStmtHandle, Viewable parent) {
   createWindowStmtHandle.getStatementLock().acquireReadLock();
   try {
     Iterator<EventBean> it = parent.iterator();
     if (!it.hasNext()) {
       return Collections.EMPTY_LIST;
     }
     ArrayDeque<EventBean> list = new ArrayDeque<EventBean>();
     while (it.hasNext()) {
       RevisionEventBeanDeclared fullRevision = (RevisionEventBeanDeclared) it.next();
       MultiKeyUntyped key = fullRevision.getKey();
       RevisionStateDeclared state = statePerKey.get(key);
       list.add(state.getLastEvent());
     }
     return list;
   } finally {
     createWindowStmtHandle.getStatementLock().releaseReadLock();
   }
 }
  public void onUpdate(
      EventBean[] newData,
      EventBean[] oldData,
      NamedWindowRootView namedWindowRootView,
      NamedWindowIndexRepository indexRepository) {
    // If new data is filled, it is not a delete
    if ((newData == null) || (newData.length == 0)) {
      // we are removing an event
      RevisionEventBeanDeclared revisionEvent = (RevisionEventBeanDeclared) oldData[0];
      MultiKeyUntyped key = revisionEvent.getKey();
      statePerKey.remove(key);

      // Insert into indexes for fast deletion, if there are any
      for (EventTable table : indexRepository.getTables()) {
        table.remove(oldData);
      }

      // make as not the latest event since its due for removal
      revisionEvent.setLatest(false);

      namedWindowRootView.updateChildren(null, oldData);
      return;
    }

    RevisionEventBeanDeclared revisionEvent = (RevisionEventBeanDeclared) newData[0];
    EventBean underlyingEvent = revisionEvent.getUnderlyingFullOrDelta();
    EventType underyingEventType = underlyingEvent.getEventType();

    // obtain key values
    MultiKeyUntyped key = null;
    RevisionTypeDesc typesDesc = null;
    boolean isBaseEventType = false;
    if (underyingEventType == baseEventType) {
      key = PropertyUtility.getKeys(underlyingEvent, fullKeyGetters);
      isBaseEventType = true;
    } else {
      typesDesc = typeDescriptors.get(underyingEventType);

      // if this type cannot be found, check all supertypes, if any
      if (typesDesc == null) {
        Iterator<EventType> superTypes = underyingEventType.getDeepSuperTypes();
        if (superTypes != null) {
          EventType superType;
          for (; superTypes.hasNext(); ) {
            superType = superTypes.next();
            if (superType == baseEventType) {
              key = PropertyUtility.getKeys(underlyingEvent, fullKeyGetters);
              isBaseEventType = true;
              break;
            }
            typesDesc = typeDescriptors.get(superType);
            if (typesDesc != null) {
              typeDescriptors.put(underyingEventType, typesDesc);
              key = PropertyUtility.getKeys(underlyingEvent, typesDesc.getKeyPropertyGetters());
              break;
            }
          }
        }
      } else {
        key = PropertyUtility.getKeys(underlyingEvent, typesDesc.getKeyPropertyGetters());
      }

      if (key == null) {
        log.warn(
            "Ignoring event of event type '"
                + underyingEventType
                + "' for revision processing type '"
                + revisionEventTypeName);
        return;
      }
    }

    // get the state for this key value
    RevisionStateDeclared revisionState = statePerKey.get(key);

    // Delta event and no full
    if ((!isBaseEventType) && (revisionState == null)) {
      return; // Ignore the event, its a delta and we don't currently have a full event for it
    }

    // New full event
    if (revisionState == null) {
      revisionState = new RevisionStateDeclared(underlyingEvent, null, null);
      statePerKey.put(key, revisionState);

      // prepare revison event
      revisionEvent.setLastBaseEvent(underlyingEvent);
      revisionEvent.setKey(key);
      revisionEvent.setHolders(null);
      revisionEvent.setLatest(true);

      // Insert into indexes for fast deletion, if there are any
      for (EventTable table : indexRepository.getTables()) {
        table.add(newData);
      }

      // post to data window
      revisionState.setLastEvent(revisionEvent);
      namedWindowRootView.updateChildren(new EventBean[] {revisionEvent}, null);
      return;
    }

    // new version
    long versionNumber = revisionState.incRevisionNumber();

    // Previously-seen full event
    if (isBaseEventType) {
      revisionState.setHolders(null);
      revisionState.setBaseEventUnderlying(underlyingEvent);
    }
    // Delta event to existing full event
    else {
      int groupNum = typesDesc.getGroup().getGroupNum();
      RevisionBeanHolder[] holders = revisionState.getHolders();
      if (holders
          == null) // optimization - the full event sets it to null, deltas all get a new one
      {
        holders = new RevisionBeanHolder[groups.length];
      } else {
        holders = arrayCopy(holders); // preserve the last revisions
      }

      // add the new revision for a property group on top
      holders[groupNum] =
          new RevisionBeanHolder(
              versionNumber, underlyingEvent, typesDesc.getChangesetPropertyGetters());
      revisionState.setHolders(holders);
    }

    // prepare revision event
    revisionEvent.setLastBaseEvent(revisionState.getBaseEventUnderlying());
    revisionEvent.setHolders(revisionState.getHolders());
    revisionEvent.setKey(key);
    revisionEvent.setLatest(true);

    // get prior event
    RevisionEventBeanDeclared lastEvent = revisionState.getLastEvent();
    lastEvent.setLatest(false);

    // data to post
    EventBean[] newDataPost = new EventBean[] {revisionEvent};
    EventBean[] oldDataPost = new EventBean[] {lastEvent};

    // update indexes
    for (EventTable table : indexRepository.getTables()) {
      table.remove(oldDataPost);
      table.add(newDataPost);
    }

    // keep reference to last event
    revisionState.setLastEvent(revisionEvent);

    namedWindowRootView.updateChildren(newDataPost, oldDataPost);
  }