public static void main(String[] args) {
   Configuration configuration = Validation.byProvider(HibernateValidator.class).configure();
   ValidatorFactory factory = configuration.buildValidatorFactory();
   Validator validator = factory.getValidator();
   validator.validate(Object.class);
   // programmation constraint mappings
   ConstraintMapping mapping = new ConstraintMapping();
 }
  @Provides
  protected ValidatorFactory getValidationFactory(
      Provider<MessageInterpolator> interpolatorProvider) {
    HibernateValidatorConfiguration configure =
        Validation.byProvider(HibernateValidator.class).configure();

    configure.messageInterpolator(interpolatorProvider.get());
    return configure.buildValidatorFactory();
  }
 static {
   HibernateValidatorConfiguration configuration =
       Validation.byProvider(HibernateValidator.class).configure().failFast(true);
   FACTORY =
       configuration
           .messageInterpolator(
               new ContextualMessageInterpolator(configuration.getDefaultMessageInterpolator()))
           .buildValidatorFactory();
 }
  @Override
  @SuppressWarnings("unchecked")
  public void afterPropertiesSet() {
    @SuppressWarnings("rawtypes")
    Configuration configuration =
        (this.providerClass != null
            ? Validation.byProvider(this.providerClass).configure()
            : Validation.byDefaultProvider().configure());

    MessageInterpolator targetInterpolator = this.messageInterpolator;
    if (targetInterpolator == null) {
      targetInterpolator = configuration.getDefaultMessageInterpolator();
    }
    configuration.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));

    if (this.traversableResolver != null) {
      configuration.traversableResolver(this.traversableResolver);
    }

    ConstraintValidatorFactory targetConstraintValidatorFactory = this.constraintValidatorFactory;
    if (targetConstraintValidatorFactory == null && this.applicationContext != null) {
      targetConstraintValidatorFactory =
          new SpringConstraintValidatorFactory(
              this.applicationContext.getAutowireCapableBeanFactory());
    }
    if (targetConstraintValidatorFactory != null) {
      configuration.constraintValidatorFactory(targetConstraintValidatorFactory);
    }

    configureParameterNameProviderIfPossible(configuration);

    if (this.mappingLocations != null) {
      for (Resource location : this.mappingLocations) {
        try {
          configuration.addMapping(location.getInputStream());
        } catch (IOException ex) {
          throw new IllegalStateException("Cannot read mapping resource: " + location);
        }
      }
    }

    for (Map.Entry<String, String> entry : this.validationPropertyMap.entrySet()) {
      configuration.addProperty(entry.getKey(), entry.getValue());
    }

    // Allow for custom post-processing before we actually build the ValidatorFactory.
    postProcessConfiguration(configuration);

    this.validatorFactory = configuration.buildValidatorFactory();
    setTargetValidator(this.validatorFactory.getValidator());
  }
  @Test
  public void failFast() {
    Validator validator =
        Validation.byProvider(HibernateValidator.class)
            .configure()
            .failFast(true)
            .buildValidatorFactory()
            .getValidator();

    Car car = new Car(null, false);

    Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car);

    assertEquals(1, constraintViolations.size());
  }
 @Test
 public void withConfiguration() {
   HibernateValidatorConfiguration configuration =
       Validation.byProvider(HibernateValidator.class)
           .providerResolver(
               new ValidationProviderResolver() {
                 @Override
                 public List<ValidationProvider<?>> getValidationProviders() {
                   ValidationProvider<HibernateValidatorConfiguration> prov =
                       new HibernateValidator();
                   List<ValidationProvider<?>> provs = new ArrayList<>();
                   provs.add(prov);
                   return provs;
                 }
               })
           .configure();
   configuration.externalClassLoader(Thread.currentThread().getContextClassLoader());
   Validator validator = configuration.buildValidatorFactory().getValidator();
   Thread.currentThread().setContextClassLoader(null);
   Set<ConstraintViolation<ValidateMe>> violations = validator.validate(new ValidateMe(0));
   Assert.assertEquals(1, violations.size());
 }
Example #7
0
  @SuppressWarnings("unchecked")
  private static Configuration<?> getConfig(final ValidationInfo info) {
    Configuration<?> target = null;
    final Thread thread = Thread.currentThread();
    final ClassLoader classLoader = thread.getContextClassLoader();

    String providerClassName = info.providerClassName;
    if (providerClassName == null) {
      providerClassName =
          SystemInstance.get().getOptions().get(VALIDATION_PROVIDER_KEY, (String) null);
    }

    if (providerClassName != null) {
      try {
        @SuppressWarnings({"unchecked", "rawtypes"})
        final Class clazz = classLoader.loadClass(providerClassName);
        target = Validation.byProvider(clazz).configure();
        logger.info("Using " + providerClassName + " as validation provider.");
      } catch (final ClassNotFoundException e) {
        logger.warning("Unable to load provider class " + providerClassName, e);
      } catch (final ValidationException ve) {
        logger.warning(
            "Unable create validator factory with provider "
                + providerClassName
                + " ("
                + ve.getMessage()
                + ")."
                + " Default one will be used.");
      }
    }
    if (target == null) {
      // force to use container provider to ignore any conflicting configuration
      thread.setContextClassLoader(ValidatorBuilder.class.getClassLoader());
      target = Validation.byDefaultProvider().configure();
      thread.setContextClassLoader(classLoader);
    }

    final Set<ExecutableType> types = new HashSet<>();
    for (final String type : info.validatedTypes) {
      types.add(ExecutableType.valueOf(type));
    }

    final Map<String, String> props = new HashMap<>();
    for (final Map.Entry<Object, Object> entry : info.propertyTypes.entrySet()) {
      final PropertyType property = new PropertyType();
      property.setName((String) entry.getKey());
      property.setValue((String) entry.getValue());

      props.put(property.getName(), property.getValue());
      if (logger.isDebugEnabled()) {
        logger.debug(
            "Found property '" + property.getName() + "' with value '" + property.getValue());
      }
      target.addProperty(property.getName(), property.getValue());
    }

    final OpenEjbBootstrapConfig bootstrapConfig =
        new OpenEjbBootstrapConfig(
            providerClassName,
            info.constraintFactoryClass,
            info.messageInterpolatorClass,
            info.traversableResolverClass,
            info.parameterNameProviderClass,
            new HashSet<>(info.constraintMappings),
            info.executableValidationEnabled,
            types,
            props);
    final OpenEjbConfig config = new OpenEjbConfig(bootstrapConfig, target);

    target.ignoreXmlConfiguration();

    final String messageInterpolatorClass = info.messageInterpolatorClass;
    if (messageInterpolatorClass != null) {
      try {
        @SuppressWarnings("unchecked")
        final Class<MessageInterpolator> clazz =
            (Class<MessageInterpolator>) classLoader.loadClass(messageInterpolatorClass);
        target.messageInterpolator(newInstance(config, clazz));
      } catch (final Exception e) {
        logger.warning(
            "Unable to set " + messageInterpolatorClass + " as message interpolator.", e);
      }
      logger.info("Using " + messageInterpolatorClass + " as message interpolator.");
    }
    final String traversableResolverClass = info.traversableResolverClass;
    if (traversableResolverClass != null) {
      try {
        @SuppressWarnings("unchecked")
        final Class<TraversableResolver> clazz =
            (Class<TraversableResolver>) classLoader.loadClass(traversableResolverClass);
        target.traversableResolver(newInstance(config, clazz));
      } catch (final Exception e) {
        logger.warning(
            "Unable to set " + traversableResolverClass + " as traversable resolver.", e);
      }
      logger.info("Using " + traversableResolverClass + " as traversable resolver.");
    }
    final String constraintFactoryClass = info.constraintFactoryClass;
    if (constraintFactoryClass != null) {
      try {
        @SuppressWarnings("unchecked")
        final Class<ConstraintValidatorFactory> clazz =
            (Class<ConstraintValidatorFactory>) classLoader.loadClass(constraintFactoryClass);
        target.constraintValidatorFactory(newInstance(config, clazz));
      } catch (final Exception e) {
        logger.warning("Unable to set " + constraintFactoryClass + " as constraint factory.", e);
      }
      logger.info("Using " + constraintFactoryClass + " as constraint factory.");
    }
    for (final String mappingFileName : info.constraintMappings) {
      if (logger.isDebugEnabled()) {
        logger.debug("Opening input stream for " + mappingFileName);
      }
      final InputStream in = classLoader.getResourceAsStream(mappingFileName);
      if (in == null) {
        logger.warning(
            "Unable to open input stream for mapping file "
                + mappingFileName
                + ". It will be ignored");
      } else {
        target.addMapping(in);
      }
    }
    if (info.parameterNameProviderClass != null) {
      try {
        final Class<ParameterNameProvider> clazz =
            (Class<ParameterNameProvider>) classLoader.loadClass(info.parameterNameProviderClass);
        target.parameterNameProvider(newInstance(config, clazz));
      } catch (final Exception e) {
        logger.warning(
            "Unable to set " + info.parameterNameProviderClass + " as parameter name provider.", e);
      }
      logger.info("Using " + info.parameterNameProviderClass + " as parameter name provider.");
    }

    return config;
  }
Example #8
0
public class QueryParser {
  private static final Logger logger = LoggerFactory.getLogger(QueryParser.class);

  private static final Validator VALIDATOR =
      Validation.byProvider(ApacheValidationProvider.class)
          .configure()
          .buildValidatorFactory()
          .getValidator();

  private AggregatorFactory m_aggregatorFactory;
  private QueryPluginFactory m_pluginFactory;
  private GroupByFactory m_groupByFactory;
  private Map<Class, Map<String, PropertyDescriptor>> m_descriptorMap;
  private final Object m_descriptorMapLock = new Object();
  private Gson m_gson;

  @Inject
  public QueryParser(
      AggregatorFactory aggregatorFactory,
      GroupByFactory groupByFactory,
      QueryPluginFactory pluginFactory) {
    m_aggregatorFactory = aggregatorFactory;
    m_groupByFactory = groupByFactory;
    m_pluginFactory = pluginFactory;

    m_descriptorMap = new HashMap<Class, Map<String, PropertyDescriptor>>();

    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory());
    builder.registerTypeAdapter(TimeUnit.class, new TimeUnitDeserializer());
    builder.registerTypeAdapter(DateTimeZone.class, new DateTimeZoneDeserializer());
    builder.registerTypeAdapter(Metric.class, new MetricDeserializer());
    builder.registerTypeAdapter(SetMultimap.class, new SetMultimapDeserializer());
    builder.registerTypeAdapter(RelativeTime.class, new RelativeTimeSerializer());
    builder.registerTypeAdapter(SetMultimap.class, new SetMultimapSerializer());
    builder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);

    m_gson = builder.create();
  }

  public Gson getGson() {
    return m_gson;
  }

  private PropertyDescriptor getPropertyDescriptor(Class objClass, String property)
      throws IntrospectionException {
    synchronized (m_descriptorMapLock) {
      Map<String, PropertyDescriptor> propMap = m_descriptorMap.get(objClass);

      if (propMap == null) {
        propMap = new HashMap<String, PropertyDescriptor>();
        m_descriptorMap.put(objClass, propMap);

        BeanInfo beanInfo = Introspector.getBeanInfo(objClass);
        PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor descriptor : descriptors) {
          propMap.put(getUnderscorePropertyName(descriptor.getName()), descriptor);
        }
      }

      return (propMap.get(property));
    }
  }

  public static String getUnderscorePropertyName(String camelCaseName) {
    StringBuilder sb = new StringBuilder();

    for (char c : camelCaseName.toCharArray()) {
      if (Character.isUpperCase(c)) sb.append('_').append(Character.toLowerCase(c));
      else sb.append(c);
    }

    return (sb.toString());
  }

  private void validateObject(Object object) throws BeanValidationException {
    validateObject(object, null);
  }

  private void validateObject(Object object, String context) throws BeanValidationException {
    // validate object using the bean validation framework
    Set<ConstraintViolation<Object>> violations = VALIDATOR.validate(object);
    if (!violations.isEmpty()) {
      throw new BeanValidationException(violations, context);
    }
  }

  public List<QueryMetric> parseQueryMetric(String json)
      throws QueryException, BeanValidationException {
    JsonParser parser = new JsonParser();
    JsonObject obj = parser.parse(json).getAsJsonObject();
    return parseQueryMetric(obj);
  }

  private List<QueryMetric> parseQueryMetric(JsonObject obj)
      throws QueryException, BeanValidationException {
    return parseQueryMetric(obj, "");
  }

  private List<QueryMetric> parseQueryMetric(JsonObject obj, String contextPrefix)
      throws QueryException, BeanValidationException {
    List<QueryMetric> ret = new ArrayList<QueryMetric>();

    Query query;
    try {
      query = m_gson.fromJson(obj, Query.class);
      validateObject(query);
    } catch (ContextualJsonSyntaxException e) {
      throw new BeanValidationException(
          new SimpleConstraintViolation(e.getContext(), e.getMessage()), "query");
    }

    JsonArray metricsArray = obj.getAsJsonArray("metrics");
    if (metricsArray == null) {
      throw new BeanValidationException(
          new SimpleConstraintViolation("metric[]", "must have a size of at least 1"),
          contextPrefix + "query");
    }

    for (int I = 0; I < metricsArray.size(); I++) {
      String context =
          (!contextPrefix.isEmpty() ? contextPrefix + "." : contextPrefix)
              + "query.metric["
              + I
              + "]";
      try {
        Metric metric = m_gson.fromJson(metricsArray.get(I), Metric.class);

        validateObject(metric, context);

        long startTime = getStartTime(query, context);
        QueryMetric queryMetric =
            new QueryMetric(startTime, query.getCacheTime(), metric.getName());
        queryMetric.setExcludeTags(metric.isExcludeTags());
        queryMetric.setLimit(metric.getLimit());

        long endTime = getEndTime(query);
        if (endTime > -1) queryMetric.setEndTime(endTime);

        if (queryMetric.getEndTime() < startTime)
          throw new BeanValidationException(
              new SimpleConstraintViolation("end_time", "must be greater than the start time"),
              context);

        queryMetric.setCacheString(query.getCacheString() + metric.getCacheString());

        JsonObject jsMetric = metricsArray.get(I).getAsJsonObject();

        JsonElement group_by = jsMetric.get("group_by");
        if (group_by != null) {
          JsonArray groupBys = group_by.getAsJsonArray();
          parseGroupBy(context, queryMetric, groupBys);
        }

        JsonElement aggregators = jsMetric.get("aggregators");
        if (aggregators != null) {
          JsonArray asJsonArray = aggregators.getAsJsonArray();
          if (asJsonArray.size() > 0)
            parseAggregators(context, queryMetric, asJsonArray, query.getTimeZone());
        }

        JsonElement plugins = jsMetric.get("plugins");
        if (plugins != null) {
          JsonArray pluginArray = plugins.getAsJsonArray();
          if (pluginArray.size() > 0) parsePlugins(context, queryMetric, pluginArray);
        }

        JsonElement order = jsMetric.get("order");
        if (order != null) queryMetric.setOrder(Order.fromString(order.getAsString(), context));

        queryMetric.setTags(metric.getTags());

        ret.add(queryMetric);
      } catch (ContextualJsonSyntaxException e) {
        throw new BeanValidationException(
            new SimpleConstraintViolation(e.getContext(), e.getMessage()), context);
      }
    }

    return (ret);
  }

  public List<RollupTask> parseRollupTasks(String json)
      throws BeanValidationException, QueryException {
    List<RollupTask> tasks = new ArrayList<RollupTask>();
    JsonParser parser = new JsonParser();
    JsonArray rollupTasks = parser.parse(json).getAsJsonArray();
    for (int i = 0; i < rollupTasks.size(); i++) {
      JsonObject taskObject = rollupTasks.get(i).getAsJsonObject();
      RollupTask task = parseRollupTask(taskObject, "tasks[" + i + "]");
      task.addJson(taskObject.toString().replaceAll("\\n", ""));
      tasks.add(task);
    }

    return tasks;
  }

  public RollupTask parseRollupTask(String json) throws BeanValidationException, QueryException {
    JsonParser parser = new JsonParser();
    JsonObject taskObject = parser.parse(json).getAsJsonObject();
    RollupTask task = parseRollupTask(taskObject, "");
    task.addJson(taskObject.toString().replaceAll("\\n", ""));
    return task;
  }

  public RollupTask parseRollupTask(JsonObject rollupTask, String context)
      throws BeanValidationException, QueryException {
    RollupTask task = m_gson.fromJson(rollupTask.getAsJsonObject(), RollupTask.class);

    validateObject(task);

    JsonArray rollups = rollupTask.getAsJsonObject().getAsJsonArray("rollups");
    if (rollups != null) {
      for (int j = 0; j < rollups.size(); j++) {
        JsonObject rollupObject = rollups.get(j).getAsJsonObject();
        Rollup rollup = m_gson.fromJson(rollupObject, Rollup.class);

        context = context + "rollup[" + j + "]";
        validateObject(rollup, context);

        JsonObject queryObject = rollupObject.getAsJsonObject("query");
        List<QueryMetric> queries = parseQueryMetric(queryObject, context);

        for (int k = 0; k < queries.size(); k++) {
          QueryMetric query = queries.get(k);
          context += ".query[" + k + "]";
          validateHasRangeAggregator(query, context);

          // Add aggregators needed for rollups
          SaveAsAggregator saveAsAggregator =
              (SaveAsAggregator) m_aggregatorFactory.createAggregator("save_as");
          saveAsAggregator.setMetricName(rollup.getSaveAs());

          TrimAggregator trimAggregator =
              (TrimAggregator) m_aggregatorFactory.createAggregator("trim");
          trimAggregator.setTrim(TrimAggregator.Trim.LAST);

          query.addAggregator(saveAsAggregator);
          query.addAggregator(trimAggregator);
        }

        rollup.addQueries(queries);
        task.addRollup(rollup);
      }
    }

    return task;
  }

  private void validateHasRangeAggregator(QueryMetric query, String context)
      throws BeanValidationException {
    boolean hasRangeAggregator = false;
    for (Aggregator aggregator : query.getAggregators()) {
      if (aggregator instanceof RangeAggregator) {
        hasRangeAggregator = true;
        break;
      }
    }

    if (!hasRangeAggregator) {
      throw new BeanValidationException(
          new SimpleConstraintViolation(
              "aggregator", "At least one aggregator must be a range aggregator"),
          context);
    }
  }

  private void parsePlugins(String context, QueryMetric queryMetric, JsonArray plugins)
      throws BeanValidationException, QueryException {
    for (int I = 0; I < plugins.size(); I++) {
      JsonObject pluginJson = plugins.get(I).getAsJsonObject();

      JsonElement name = pluginJson.get("name");
      if (name == null || name.getAsString().isEmpty())
        throw new BeanValidationException(
            new SimpleConstraintViolation("plugins[" + I + "]", "must have a name"), context);

      String pluginContext = context + ".plugins[" + I + "]";
      String pluginName = name.getAsString();
      QueryPlugin plugin = m_pluginFactory.createQueryPlugin(pluginName);

      if (plugin == null)
        throw new BeanValidationException(
            new SimpleConstraintViolation(pluginName, "invalid query plugin name"), pluginContext);

      deserializeProperties(pluginContext, pluginJson, pluginName, plugin);

      validateObject(plugin, pluginContext);

      queryMetric.addPlugin(plugin);
    }
  }

  private void parseAggregators(
      String context, QueryMetric queryMetric, JsonArray aggregators, DateTimeZone timeZone)
      throws QueryException, BeanValidationException {
    for (int J = 0; J < aggregators.size(); J++) {
      JsonObject jsAggregator = aggregators.get(J).getAsJsonObject();

      JsonElement name = jsAggregator.get("name");
      if (name == null || name.getAsString().isEmpty())
        throw new BeanValidationException(
            new SimpleConstraintViolation("aggregators[" + J + "]", "must have a name"), context);

      String aggContext = context + ".aggregators[" + J + "]";
      String aggName = name.getAsString();
      Aggregator aggregator = m_aggregatorFactory.createAggregator(aggName);

      if (aggregator == null)
        throw new BeanValidationException(
            new SimpleConstraintViolation(aggName, "invalid aggregator name"), aggContext);

      // If it is a range aggregator we will default the start time to
      // the start of the query.
      if (aggregator instanceof RangeAggregator) {
        RangeAggregator ra = (RangeAggregator) aggregator;
        ra.setStartTime(queryMetric.getStartTime());
      }

      if (aggregator instanceof TimezoneAware) {
        TimezoneAware ta = (TimezoneAware) aggregator;
        ta.setTimeZone(timeZone);
      }

      if (aggregator instanceof GroupByAware) {
        GroupByAware groupByAware = (GroupByAware) aggregator;
        groupByAware.setGroupBys(queryMetric.getGroupBys());
      }

      deserializeProperties(aggContext, jsAggregator, aggName, aggregator);

      validateObject(aggregator, aggContext);

      queryMetric.addAggregator(aggregator);
    }
  }

  private void parseGroupBy(String context, QueryMetric queryMetric, JsonArray groupBys)
      throws QueryException, BeanValidationException {
    for (int J = 0; J < groupBys.size(); J++) {
      String groupContext = "group_by[" + J + "]";
      JsonObject jsGroupBy = groupBys.get(J).getAsJsonObject();

      JsonElement nameElement = jsGroupBy.get("name");
      if (nameElement == null || nameElement.getAsString().isEmpty())
        throw new BeanValidationException(
            new SimpleConstraintViolation(groupContext, "must have a name"), context);

      String name = nameElement.getAsString();

      GroupBy groupBy = m_groupByFactory.createGroupBy(name);
      if (groupBy == null)
        throw new BeanValidationException(
            new SimpleConstraintViolation(groupContext + "." + name, "invalid group_by name"),
            context);

      deserializeProperties(context + "." + groupContext, jsGroupBy, name, groupBy);
      validateObject(groupBy, context + "." + groupContext);

      groupBy.setStartDate(queryMetric.getStartTime());

      queryMetric.addGroupBy(groupBy);
    }
  }

  private void deserializeProperties(
      String context, JsonObject jsonObject, String name, Object object)
      throws QueryException, BeanValidationException {
    Set<Map.Entry<String, JsonElement>> props = jsonObject.entrySet();
    for (Map.Entry<String, JsonElement> prop : props) {
      String property = prop.getKey();
      if (property.equals("name")) continue;

      PropertyDescriptor pd = null;
      try {
        pd = getPropertyDescriptor(object.getClass(), property);
      } catch (IntrospectionException e) {
        logger.error("Introspection error on " + object.getClass(), e);
      }

      if (pd == null) {
        String msg =
            "Property '"
                + property
                + "' was specified for object '"
                + name
                + "' but no matching setter was found on '"
                + object.getClass()
                + "'";

        throw new QueryException(msg);
      }

      Class propClass = pd.getPropertyType();

      Object propValue;
      try {
        propValue = m_gson.fromJson(prop.getValue(), propClass);
        validateObject(propValue, context + "." + property);
      } catch (ContextualJsonSyntaxException e) {
        throw new BeanValidationException(
            new SimpleConstraintViolation(e.getContext(), e.getMessage()), context);
      } catch (NumberFormatException e) {
        throw new BeanValidationException(
            new SimpleConstraintViolation(property, e.getMessage()), context);
      }

      Method method = pd.getWriteMethod();
      if (method == null) {
        String msg =
            "Property '"
                + property
                + "' was specified for object '"
                + name
                + "' but no matching setter was found on '"
                + object.getClass().getName()
                + "'";

        throw new QueryException(msg);
      }

      try {
        method.invoke(object, propValue);
      } catch (Exception e) {
        logger.error("Invocation error: ", e);
        String msg =
            "Call to "
                + object.getClass().getName()
                + ":"
                + method.getName()
                + " failed with message: "
                + e.getMessage();

        throw new QueryException(msg);
      }
    }
  }

  private long getStartTime(Query request, String context) throws BeanValidationException {
    if (request.getStartAbsolute() != null) {
      return request.getStartAbsolute();
    } else if (request.getStartRelative() != null) {
      return request.getStartRelative().getTimeRelativeTo(System.currentTimeMillis());
    } else {
      throw new BeanValidationException(
          new SimpleConstraintViolation("start_time", "relative or absolute time must be set"),
          context);
    }
  }

  private long getEndTime(Query request) {
    if (request.getEndAbsolute() != null) return request.getEndAbsolute();
    else if (request.getEndRelative() != null)
      return request.getEndRelative().getTimeRelativeTo(System.currentTimeMillis());
    return -1;
  }

  // ===========================================================================
  private static class Metric {
    @NotNull
    @NotEmpty()
    @SerializedName("name")
    private String name;

    @SerializedName("tags")
    private SetMultimap<String, String> tags;

    @SerializedName("exclude_tags")
    private boolean exclude_tags;

    @SerializedName("limit")
    private int limit;

    public Metric(String name, boolean exclude_tags, TreeMultimap<String, String> tags) {
      this.name = name;
      this.tags = tags;
      this.exclude_tags = exclude_tags;
      this.limit = 0;
    }

    public String getName() {
      return name;
    }

    public int getLimit() {
      return limit;
    }

    public void setLimit(int limit) {
      this.limit = limit;
    }

    private boolean isExcludeTags() {
      return exclude_tags;
    }

    public String getCacheString() {
      StringBuilder sb = new StringBuilder();

      sb.append(name).append(":");

      for (Map.Entry<String, String> tagEntry : tags.entries()) {
        sb.append(tagEntry.getKey()).append("=");
        sb.append(tagEntry.getValue()).append(":");
      }

      return (sb.toString());
    }

    public SetMultimap<String, String> getTags() {
      if (tags != null) {
        return tags;
      } else {
        return HashMultimap.create();
      }
    }
  }

  // ===========================================================================
  private static class Query {
    @SerializedName("start_absolute")
    private Long m_startAbsolute;

    @SerializedName("end_absolute")
    private Long m_endAbsolute;

    @Min(0)
    @SerializedName("cache_time")
    private int cache_time;

    @Valid
    @SerializedName("start_relative")
    private RelativeTime start_relative;

    @Valid
    @SerializedName("end_relative")
    private RelativeTime end_relative;

    @Valid
    @SerializedName("time_zone")
    private DateTimeZone m_timeZone; // = DateTimeZone.UTC;;

    public Long getStartAbsolute() {
      return m_startAbsolute;
    }

    public Long getEndAbsolute() {
      return m_endAbsolute;
    }

    public int getCacheTime() {
      return cache_time;
    }

    public RelativeTime getStartRelative() {
      return start_relative;
    }

    public RelativeTime getEndRelative() {
      return end_relative;
    }

    public DateTimeZone getTimeZone() {
      return m_timeZone;
    }

    public String getCacheString() {
      StringBuilder sb = new StringBuilder();
      if (m_startAbsolute != null) sb.append(m_startAbsolute).append(":");

      if (start_relative != null) sb.append(start_relative.toString()).append(":");

      if (m_endAbsolute != null) sb.append(m_endAbsolute).append(":");

      if (end_relative != null) sb.append(end_relative.toString()).append(":");

      return (sb.toString());
    }

    @Override
    public String toString() {
      return "Query{"
          + "startAbsolute='"
          + m_startAbsolute
          + '\''
          + ", endAbsolute='"
          + m_endAbsolute
          + '\''
          + ", cache_time="
          + cache_time
          + ", startRelative="
          + start_relative
          + ", endRelative="
          + end_relative
          + '}';
    }
  }

  // ===========================================================================
  private static class LowercaseEnumTypeAdapterFactory implements TypeAdapterFactory {
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {

      @SuppressWarnings("unchecked")
      Class<T> rawType = (Class<T>) type.getRawType();
      if (!rawType.isEnum()) {
        return null;
      }

      final Map<String, T> lowercaseToConstant = new HashMap<String, T>();
      for (T constant : rawType.getEnumConstants()) {
        lowercaseToConstant.put(toLowercase(constant), constant);
      }

      return new TypeAdapter<T>() {
        public void write(JsonWriter out, T value) throws IOException {
          if (value == null) {
            out.nullValue();
          } else {
            out.value(toLowercase(value));
          }
        }

        public T read(JsonReader reader) throws IOException {
          if (reader.peek() == JsonToken.NULL) {
            reader.nextNull();
            return null;
          } else {
            return lowercaseToConstant.get(reader.nextString());
          }
        }
      };
    }

    private String toLowercase(Object o) {
      return o.toString().toLowerCase(Locale.US);
    }
  }

  // ===========================================================================
  private class TimeUnitDeserializer implements JsonDeserializer<TimeUnit> {
    public TimeUnit deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
        throws JsonParseException {
      String unit = json.getAsString();
      TimeUnit tu;

      try {
        tu = TimeUnit.from(unit);
      } catch (IllegalArgumentException e) {
        throw new ContextualJsonSyntaxException(
            unit, "is not a valid time unit, must be one of " + TimeUnit.toValueNames());
      }

      return tu;
    }
  }

  // ===========================================================================
  private class DateTimeZoneDeserializer implements JsonDeserializer<DateTimeZone> {
    public DateTimeZone deserialize(
        JsonElement json, Type typeOfT, JsonDeserializationContext context)
        throws JsonParseException {
      if (json.isJsonNull()) return null;
      String tz = json.getAsString();
      if (tz.isEmpty()) // defaults to UTC
      return DateTimeZone.UTC;
      DateTimeZone timeZone;

      try {
        // check if time zone is valid
        timeZone = DateTimeZone.forID(tz);
      } catch (IllegalArgumentException e) {
        throw new ContextualJsonSyntaxException(
            tz, "is not a valid time zone, must be one of " + DateTimeZone.getAvailableIDs());
      }
      return timeZone;
    }
  }

  // ===========================================================================
  private class MetricDeserializer implements JsonDeserializer<Metric> {
    @Override
    public Metric deserialize(
        JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext)
        throws JsonParseException {
      JsonObject jsonObject = jsonElement.getAsJsonObject();

      String name = null;
      if (jsonObject.get("name") != null) name = jsonObject.get("name").getAsString();

      boolean exclude_tags = false;
      if (jsonObject.get("exclude_tags") != null)
        exclude_tags = jsonObject.get("exclude_tags").getAsBoolean();

      TreeMultimap<String, String> tags = TreeMultimap.create();
      JsonElement jeTags = jsonObject.get("tags");
      if (jeTags != null) {
        JsonObject joTags = jeTags.getAsJsonObject();
        int count = 0;
        for (Map.Entry<String, JsonElement> tagEntry : joTags.entrySet()) {
          String context = "tags[" + count + "]";
          if (tagEntry.getKey().isEmpty())
            throw new ContextualJsonSyntaxException(context, "name must not be empty");

          if (tagEntry.getValue().isJsonArray()) {
            for (JsonElement element : tagEntry.getValue().getAsJsonArray()) {
              if (element.isJsonNull() || element.getAsString().isEmpty())
                throw new ContextualJsonSyntaxException(
                    context + "." + tagEntry.getKey(), "value must not be null or empty");
              tags.put(tagEntry.getKey(), element.getAsString());
            }
          } else {
            if (tagEntry.getValue().isJsonNull() || tagEntry.getValue().getAsString().isEmpty())
              throw new ContextualJsonSyntaxException(
                  context + "." + tagEntry.getKey(), "value must not be null or empty");
            tags.put(tagEntry.getKey(), tagEntry.getValue().getAsString());
          }
          count++;
        }
      }

      Metric ret = new Metric(name, exclude_tags, tags);

      JsonElement limit = jsonObject.get("limit");
      if (limit != null) ret.setLimit(limit.getAsInt());

      return (ret);
    }
  }

  // ===========================================================================
  private static class ContextualJsonSyntaxException extends RuntimeException {
    private String context;

    private ContextualJsonSyntaxException(String context, String msg) {
      super(msg);
      this.context = context;
    }

    private String getContext() {
      return context;
    }
  }

  // ===========================================================================
  public static class SimpleConstraintViolation implements ConstraintViolation<Object> {
    private String message;
    private String context;

    public SimpleConstraintViolation(String context, String message) {
      this.message = message;
      this.context = context;
    }

    @Override
    public String getMessage() {
      return message;
    }

    @Override
    public String getMessageTemplate() {
      return null;
    }

    @Override
    public Object getRootBean() {
      return null;
    }

    @Override
    public Class<Object> getRootBeanClass() {
      return null;
    }

    @Override
    public Object getLeafBean() {
      return null;
    }

    @Override
    public Path getPropertyPath() {
      return new SimplePath(context);
    }

    @Override
    public Object getInvalidValue() {
      return null;
    }

    @Override
    public ConstraintDescriptor<?> getConstraintDescriptor() {
      return null;
    }
  }

  private static class SimplePath implements Path {
    private String context;

    private SimplePath(String context) {
      this.context = context;
    }

    @Override
    public Iterator<Node> iterator() {
      return null;
    }

    @Override
    public String toString() {
      return context;
    }
  }
}
 @Test
 public void testBootstrapAsServiceWithBuilder() {
   HibernateValidatorConfiguration configuration =
       Validation.byProvider(HibernateValidationProvider.class).configure();
   assertDefaultBuilderAndFactory(configuration);
 }
 public static <T extends Configuration<T>, U extends ValidationProvider<T>>
     ProviderSpecificBootstrap<T> byProvider(Class<U> providerType) {
   ProviderSpecificBootstrap<T> bootstrap = Validation.byProvider(providerType);
   return new ProviderSpecificBootstrapWrapper<T>(bootstrap);
 }