/**
   * TODO: Description.
   *
   * @param source
   * @param target
   * @param syncOperation the parent {@link ObjectMapping.SyncOperation} instance
   * @return TODO.
   * @throws SynchronizationException TODO.
   */
  public Action getAction(
      LazyObjectAccessor source,
      LazyObjectAccessor target,
      final ObjectMapping.SyncOperation syncOperation)
      throws SynchronizationException {
    Action result = null;
    if (action != null) { // static action specified
      result = action;
    } else if (script != null) { // action is dynamically determine
      Map<String, Object> scope = new HashMap<String, Object>();
      if (null != scriptScope) {
        // Make a thread safe copy and put the variables into the scope
        for (Map.Entry<String, Object> entry : Utils.deepCopy(scriptScope).entrySet()) {
          if (scope.containsKey(entry.getKey())) {
            continue;
          }
          scope.put(entry.getKey(), entry.getValue());
        }
      }
      Map<String, Object> recon = new HashMap<String, Object>();
      scope.put("recon", recon);
      JsonValue actionParam = null;
      if (syncOperation instanceof ObjectMapping.TargetSyncOperation) {
        actionParam = ((ObjectMapping.TargetSyncOperation) syncOperation).toJsonValue();
      } else if (syncOperation instanceof ObjectMapping.SourceSyncOperation) {
        actionParam = ((ObjectMapping.SourceSyncOperation) syncOperation).toJsonValue();
      }
      if (null != actionParam) {
        // FIXME Decide if leading underscore should be used here or not
        actionParam.put("_" + ActionRequest.FIELD_ACTION, "performAction");
        recon.put("actionParam", actionParam.getObject());
      }

      scope.put("sourceAction", (syncOperation instanceof ObjectMapping.SourceSyncOperation));
      if (source != null) {
        scope.put("source", source.asMap());
      }
      if (target != null) {
        scope.put("target", target.asMap());
      }
      try {
        result = Enum.valueOf(Action.class, script.exec(scope).toString());
      } catch (NullPointerException npe) {
        throw new SynchronizationException("action script returned null value");
      } catch (IllegalArgumentException iae) {
        throw new SynchronizationException("action script returned invalid action");
      } catch (ScriptException se) {
        LOGGER.debug("action script encountered exception", se);
        throw new SynchronizationException(se);
      }
    }
    return result;
  }
 public void evaluatePostAction(
     LazyObjectAccessor source, LazyObjectAccessor target, Action action, boolean sourceAction)
     throws SynchronizationException {
   if (postAction != null) {
     Map<String, Object> scope = new HashMap<String, Object>();
     scope.put("sourceAction", sourceAction);
     scope.put("action", action.name());
     scope.put("situation", situation.name());
     if (source != null) {
       scope.put("source", source.asMap());
     }
     if (target != null) {
       scope.put("target", target.asMap());
     }
     try {
       postAction.exec(scope);
     } catch (ScriptException se) {
       LOGGER.debug("action script encountered exception", se);
       throw new SynchronizationException(se);
     }
   }
 }