@Override
  public void storeExternalValue(PropertyContext propertyContext, String value, String type) {

    if (!(this
        instanceof
        XFormsSelectControl)) { // kind of a HACK due to the way our class hierarchy is setup
      // Handle xforms:select1-specific logic

      // Decrypt incoming value. With open selection, values are sent to the client.
      if (isEncryptItemValues()) {
        try {
          value = XFormsItemUtils.decryptValue(propertyContext, value);
        } catch (IllegalArgumentException e) {
          getIndentedLogger()
              .logError(
                  "", "exception decrypting value", "control id", getEffectiveId(), "value", value);
          throw e;
        }
      }

      // Current control value
      final String controlValue = getValue(propertyContext);

      // Iterate over all the items
      final Itemset itemset = getItemset(propertyContext);
      final List<XFormsEvent> selectEvents = new ArrayList<XFormsEvent>();
      final List<XFormsEvent> deselectEvents = new ArrayList<XFormsEvent>();
      if (itemset != null) {
        for (Item currentItem : itemset.toList()) {
          final String currentItemValue = currentItem.getValue();
          final boolean itemWasSelected = controlValue.equals(currentItemValue);
          final boolean itemIsSelected;
          if (value.equals(currentItemValue)) {
            // Value is currently selected in the UI
            itemIsSelected = true;
          } else {
            // Value is currently NOT selected in the UI
            itemIsSelected = false;
          }

          // Handle xforms-select / xforms-deselect
          // TODO: Dispatch to itemset or item once we support doing that
          if (!itemWasSelected && itemIsSelected) {
            selectEvents.add(new XFormsSelectEvent(containingDocument, this, currentItemValue));
          } else if (itemWasSelected && !itemIsSelected) {
            deselectEvents.add(new XFormsDeselectEvent(containingDocument, this, currentItemValue));
          }
        }
      }

      // Dispatch xforms-deselect events
      if (deselectEvents.size() > 0) {
        for (XFormsEvent currentEvent : deselectEvents) {
          currentEvent
              .getTargetObject()
              .getXBLContainer(containingDocument)
              .dispatchEvent(propertyContext, currentEvent);
        }
      }
      // Select events must be sent after all xforms-deselect events
      final boolean hasSelectedItem = selectEvents.size() > 0;
      if (hasSelectedItem) {
        for (XFormsEvent currentEvent : selectEvents) {
          currentEvent
              .getTargetObject()
              .getXBLContainer(containingDocument)
              .dispatchEvent(propertyContext, currentEvent);
        }
      }

      if (hasSelectedItem || isOpenSelection()) {
        // Only then do we store the external value. This ensures that if the value is NOT in the
        // itemset AND
        // we are a closed selection then we do NOT store the value in instance.
        super.storeExternalValue(propertyContext, value, type);
      }
    } else {
      // Forward to superclass
      super.storeExternalValue(propertyContext, value, type);
    }
  }
 public Script(String functionName, XFormsEvent event, XFormsEventObserver eventObserver) {
   this.functionName = functionName;
   this.targetEffectiveId = event.targetObject().getEffectiveId();
   this.observerEffectiveId = eventObserver.getEffectiveId();
 }