public static function validate($value, $validateDesc, $context=null) {

    // get validator list
    $validators = [];

    // split validateTypeDesc by commas and colons (separates validateType from options)
    $validateDescParts = [];
    preg_match_all('/\{(?:[^{}]|(?R))+\}|[^{}:,\s]+/', $validateDesc, $validateDescParts);
    // combine validateType and options again
    foreach ($validateDescParts[0] as $validateDescPart) {
      if (preg_match('/^\{.*?\}$/', $validateDescPart)) {
        // options of preceding validator
        $numValidators = sizeof($validators);
        if ($numValidators > 0) {
          $validators[$numValidators-1] .= ':'.$validateDescPart;
        }
      }
      else {
        $validators[] = $validateDescPart;
      }
    }

    // validate against each validator
    foreach ($validators as $validator) {
      list($validateTypeName, $validateOptions) = array_pad(preg_split('/:/', $validator, 2), 2, null);

      // get the validator that should be used for this value
      $validatorInstance = self::getValidateType($validateTypeName);
      if ($validateOptions !== null) {
        $decodedOptions = json_decode($validateOptions, true);
        if ($decodedOptions === null) {
          throw new ConfigurationException("No valid JSON format: ".$validateOptions);
        }
        $validateOptions = $decodedOptions;
      }
      if (!$validatorInstance->validate($value, $validateOptions, $context)) {
        return false;
      }
    }

    // all validators passed
    return true;
  }