View Javadoc

1   /*
2    * Copyright 2013 University of Glasgow.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package broadwick.config;
17  
18  import broadwick.config.generated.Models;
19  import broadwick.config.generated.Project;
20  import broadwick.model.Model;
21  import lombok.extern.slf4j.Slf4j;
22  
23  /**
24   * Validator class for configuration files supplied to Broadwick, the framework for epidemiological modelling.
25   */
26  @Slf4j
27  public final class ConfigValidator {
28  
29      /**
30       * Create an validator instance that is capable of checking the content of a configuration file.
31       * @param project the contents of the [read] configuration file. project.
32       */
33      public ConfigValidator(final Project project) {
34          this.project = project;
35      }
36  
37      /**
38       * Validate the project.
39       * @return a ConfigValidationErrors object that contains all the errors (if any).
40       */
41      public ConfigValidationErrors validate() {
42          try {
43              validateModels();
44          } catch (Exception e) {
45              errors.addError("Could not validate the configuration file. " + e.getLocalizedMessage());
46          }
47  
48          return errors;
49      }
50  
51      /**
52       * Validate the Models section of the configuration file. Any errors will be saved in the local ValidationErrors.
53       */
54      private void validateModels() {
55          for (Models.Model model : project.getModels().getModel()) {
56  
57              // we create (using reflection) the model(s) in the configuration file and check that the parameters
58              // and priors in the configuration file are valid for the model (by checking that the model has fields
59              // marked with the @Parameter and @Prior annotations).
60              final String clazz = model.getClassname();
61              final Model modelObj = this.<Model>createObject(Model.class, clazz);
62  
63              if (modelObj == null) {
64                  errors.addError(String.format("Could not create class [%s]. Does it exist?", clazz));
65              }
66              // TODO else perform any validation
67          }
68      }
69  
70      /**
71       * If the project has been validated, i.e. it is structurally ok, then this method will simply return the project
72       * supplied in this objects constructor, else it will return null.
73       * @return null if the project is invalid (i.e. contains major errors) else returns the project object supplied to
74       *         the constructor.
75       */
76      public Project getValidatedProject() {
77          if (errors.isValid()) {
78              return project;
79          } else {
80              return null;
81          }
82      }
83  
84      /**
85       * Create an object through reflection, to use this method to create a solver object
86       * <code>
87       * Solver solverObj = this.<Solver>createObject(Solver.class, "RungeKutta4");
88       * </code>
89       * @param <T>   the type of object to create.
90       * @param clazz the class type of the object we will create.
91       * @param name  the name of the class that is to be instantiated.
92       * @return the created object.
93       */
94      private <T> T createObject(final Class<T> clazz, final String name) {
95          T object = null;
96          try {
97              // Check if the class exists
98              object = clazz.cast(Class.forName(name).newInstance());
99  
100         } catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) {
101             errors.addError("Could not find " + clazz.getCanonicalName() + " class <" + name + ">");
102         }
103         return object;
104     }
105 
106     private Project project;
107     private ConfigValidationErrors errors = new ConfigValidationErrors();
108 }