class SchedulerFactory {

    public List<Scheduler> parseSchedulers(Buffer buffer) throws ValidationException {
        List<Scheduler> result = new ArrayList<>();
        String configString;
        try {
            configString = StringUtils.replaceWildcardConfigs(buffer.toString("UTF-8"), properties);
        } catch(Exception e){
            throw new ValidationException(e);
        }

        ValidationResult validationResult = Validator.validateStatic(Buffer.buffer(configString), schedulersSchema, log);
        if(!validationResult.isSuccess()){
            throw new  ValidationException(validationResult);
        }

        JsonObject mainObject = new JsonObject(configString);
        for(Map.Entry<String,Object> entry: mainObject.getJsonObject(SCHEDULERS).getMap().entrySet()) {
            Map<String,Object> schedulerJson = (Map<String,Object>)entry.getValue();

            boolean executeOnStartup = false;
            boolean executeOnReload = false;
            if ( schedulerJson.containsKey(EXECUTE_ON_STARTUP) ) {
                executeOnStartup = (boolean) schedulerJson.get(EXECUTE_ON_STARTUP);

                // reload is always as a default performed, if startup execution is enforced
                executeOnReload = executeOnStartup;
            }

            // do we need to fire a scheduler on a reload?
            if ( schedulerJson.containsKey(EXECUTE_ON_RELOAD) ) {
                executeOnReload = (boolean) schedulerJson.get(EXECUTE_ON_RELOAD);
            }


                int maxRandomOffset = 0;
            if ( schedulerJson.containsKey(RANDOM_OFFSET) ) {
                try {
                    maxRandomOffset = (Integer) schedulerJson.get(RANDOM_OFFSET);
                }
                catch(NumberFormatException e) {
                    throw new ValidationException("Could not parse " + RANDOM_OFFSET + " of scheduler '"+entry.getKey()+"'", e);
                }
            }

            List<HttpRequest> requests = new ArrayList<>();
            for(int i = 0; i< ((ArrayList<Object>)schedulerJson.get(REQUESTS)).size(); i++) {
                try {
                    requests.add(new HttpRequest(prepare((JsonObject) mainObject.getJsonObject(SCHEDULERS).getJsonObject(entry.getKey()).getJsonArray(REQUESTS).getValue(i))));
                } catch(Exception e) {
                    throw new ValidationException("Could not parse request ["+i+"] of scheduler "+entry.getKey(), e);
                }
            }
            try {
                result.add(new Scheduler(vertx, redisquesAddress, redisClient, entry.getKey(), (String)schedulerJson.get("cronExpression"), requests, monitoringHandler, maxRandomOffset, executeOnStartup, executeOnReload));
            } catch (ParseException e) {
                throw new ValidationException("Could not parse cron expression of scheduler '"+entry.getKey()+"'", e);
            }
        }
        return result;
    }

    public  SchedulerFactory(Map<String, Object> properties, Vertx vertx, RedisClient redisClient, MonitoringHandler monitoringHandler, String schedulersSchema, String redisquesAddress);

}