// HACK: reflection
 private void updateScenarioParameters() {
   for (ConfigurableObject configObj : this.scenarioParameters.values()) {
     String beanName = configObj.getId();
     Object bean = this.context.getBean(beanName);
     Class<?> clazz = bean.getClass();
     HashMap<String, java.lang.reflect.Field> declaredFields =
         new HashMap<String, java.lang.reflect.Field>();
     do {
       for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {
         declaredFields.put(field.getName(), field);
       }
       clazz = clazz.getSuperclass();
     } while (clazz != null);
     clazz = bean.getClass();
     for (ScenarioParameter parameter : configObj.getParameters()) {
       String field = this.capitalize(parameter.getField());
       Object value = parameter.getValue();
       Method[] methods = clazz.getMethods();
       for (Method method : methods) {
         if (method.getName().equals("set" + field)) {
           try {
             method.invoke(bean, value);
           } catch (Exception e) {
             throw new RuntimeException(e);
           }
           ((NodeBacked) bean).persist();
           break;
         }
       }
     }
   }
 }
 @RequestMapping(value = "/save", method = RequestMethod.POST)
 @ResponseBody
 public JsonResponse save(
     @RequestParam("ids") String[] ids,
     @RequestParam("counts") int[] counts,
     @RequestParam("fields") String[] fields,
     @RequestParam("values") String[] values) {
   Map<String, Map<String, ScenarioParameter>> params =
       new HashMap<String, Map<String, ScenarioParameter>>();
   Map<String, ConfigurableObject> oldParams = this.engineService.getScenarioParameters();
   int countsum = 0;
   String error = null;
   for (int i = 0; i < ids.length; i++) {
     Map<String, ScenarioParameter> p = new HashMap<String, ScenarioParameter>();
     for (int j = countsum; j < countsum + counts[i]; j++) {
       Object value;
       ConfigurableObject obj = oldParams.get(ids[i]);
       ScenarioParameter param = obj.getParameter(fields[j]);
       try {
         value = this.parseValue(param.getValue(), values[j]);
       } catch (IllegalArgumentException e) {
         error =
             "Incorrect value for '"
                 + ids[i]
                 + "' field '"
                 + fields[j]
                 + "' ("
                 + e.getMessage()
                 + ")";
         break;
       }
       p.put(fields[j], new ScenarioParameter(fields[j], value));
     }
     if (error != null) break;
     params.put(ids[i], p);
     countsum += counts[i];
   }
   if (error == null) {
     this.engineService.setScenarioParameters(params);
     return new JsonResponse(true);
   } else {
     JsonResponse response = new JsonResponse(false);
     response.setError(error);
     return response;
   }
 }
 @Override
 public synchronized void setScenarioParameters(
     Map<String, Map<String, ScenarioParameter>> parameters) {
   // perform sanity check first to avoid exploitation by hackers
   for (String obj : parameters.keySet()) {
     if (!this.scenarioParameters.containsKey(obj)) {
       throw new RuntimeException("Object with id '" + obj + "' can not be configured");
     }
     ConfigurableObject oldObj = this.scenarioParameters.get(obj);
     Map<String, ScenarioParameter> newParams = parameters.get(obj);
     for (String field : newParams.keySet()) {
       if (!oldObj.containsParam(field)) {
         throw new RuntimeException(
             "'" + obj + "'" + " has no configurable field '" + field + "'");
       }
       ScenarioParameter newParam = newParams.get(field);
       oldObj.setParamValue(field, newParam.getValue());
     }
   }
   this.updateScenarioParameters();
 }
  private synchronized void loadScenario(Scenario scenario) {
    if (this.simulation.getState() != EngineState.STOPPED
        && this.simulation.getState() != EngineState.CRASHED) return;

    boolean found = false;
    for (Scenario scen : this.scenarios) {
      if (scenario.equals(scen)) {
        found = true;
        break;
      }
    }
    if (!found) throw new RuntimeException("Scenario " + scenario.getName() + " does not exist");

    if (this.context != null) {
      this.context.close();
    }
    try {
      this.graph.clear();
    } catch (Exception err) {
      logger.error("Error clearing graph", err);
    }
    String[] configs = {SCENARIO_FOLDER + "/" + scenario.getName()};
    this.context = new ClassPathXmlApplicationContext(configs, this.applicationContext);

    if (!this.currentScenario.equals(found) || this.scenarioParameters.isEmpty()) {
      this.scenarioParameters.clear();

      String[] names = this.context.getBeanNamesForType(Object.class);
      for (String beanName : names) {
        Object bean = this.context.getBean(beanName);
        ArrayList<java.lang.reflect.Field> fields = new ArrayList<java.lang.reflect.Field>();
        Class<?> clazz = bean.getClass();
        do {
          for (java.lang.reflect.Field field : clazz.getDeclaredFields()) {
            fields.add(field);
          }
          clazz = clazz.getSuperclass();
        } while (clazz != null);
        clazz = bean.getClass();
        for (java.lang.reflect.Field field : fields) {
          String name = field.getName();
          SimulationParameter annotation = field.getAnnotation(SimulationParameter.class);
          if (annotation != null) {
            Object value = null;
            try {
              Method getter;
              Class<?> fieldType = field.getType();
              if (fieldType.equals(Boolean.class) || fieldType.equals(boolean.class)) {
                getter = bean.getClass().getMethod("is" + this.capitalize(name));
              } else {
                getter = bean.getClass().getMethod("get" + this.capitalize(name));
              }
              value = getter.invoke(bean);
            } catch (Exception e) {
              throw new RuntimeException(e);
            }
            ConfigurableObject cfgObj = this.scenarioParameters.get(beanName);
            if (cfgObj == null) {
              cfgObj = new ConfigurableObject(beanName, clazz.getName());
              this.scenarioParameters.put(beanName, cfgObj);
            }
            ScenarioParameter parameter = new ScenarioParameter(name, value, annotation.label());
            if (!Double.isNaN(annotation.from()) && !Double.isNaN(annotation.to())) {
              parameter.setFrom(annotation.from());
              parameter.setTo(annotation.to());
            }
            if (!Double.isNaN(annotation.step())) {
              parameter.setStep(annotation.step());
            }
            cfgObj.addParameter(parameter);
          }
        }
      }
    }

    this.currentScenario = scenario;
    this.scenarioLoaded = true;
  }