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 }