Check.java 8.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*-
 *  Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
 * 
 *  This file is part of CityDoctor2.
 *
 *  CityDoctor2 is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  CityDoctor2 is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with CityDoctor2.  If not, see <https://www.gnu.org/licenses/>.
 */
package de.hft.stuttgart.citydoctor2.check;

Matthias Betz's avatar
Matthias Betz committed
21
22
import java.lang.reflect.Method;
import java.util.ArrayList;
23
24
25
import java.util.Collections;
import java.util.List;
import java.util.Map;
26
import java.util.Set;
27
28
29
30
31
32
33
34
35
36
37
38
39
40

import de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError;
import de.hft.stuttgart.citydoctor2.datastructure.AbstractBuilding;
import de.hft.stuttgart.citydoctor2.datastructure.BoundarySurface;
import de.hft.stuttgart.citydoctor2.datastructure.BridgeObject;
import de.hft.stuttgart.citydoctor2.datastructure.Building;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingInstallation;
import de.hft.stuttgart.citydoctor2.datastructure.BuildingPart;
import de.hft.stuttgart.citydoctor2.datastructure.CityObject;
import de.hft.stuttgart.citydoctor2.datastructure.Geometry;
import de.hft.stuttgart.citydoctor2.datastructure.LandObject;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Opening;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
41
42
import de.hft.stuttgart.citydoctor2.datastructure.ReliefObject;
import de.hft.stuttgart.citydoctor2.datastructure.TinObject;
43
44
45
46
47
48
49
50
51
import de.hft.stuttgart.citydoctor2.datastructure.TransportationObject;
import de.hft.stuttgart.citydoctor2.datastructure.Vegetation;
import de.hft.stuttgart.citydoctor2.datastructure.WaterObject;
import de.hft.stuttgart.citydoctor2.parser.ParserConfiguration;

/**
 * The general check class containing the methods which will be called by check
 * engine. To create a new check override one or more check(...) methods and
 * implement the {@link Check#getApplicableToClasses()} method by returning a
Matthias Betz's avatar
Matthias Betz committed
52
53
54
55
56
57
58
59
60
61
 * list of classes you wish to check.<br>
 * CheckResult objects can be attached to every Checkable. If the check has
 * parameters override the {@link Check#init(Map, ParserConfiguration)} method
 * to get the value of a parameter if a user has specified one in the validation
 * plan. It will be contained in the Map as a string. If you have parameters you
 * will need to override the {@link Check#getDefaultParameter()} method as well
 * to declare which parameters you have, which name and default value they have.
 * The name will be the key for the Map in the init method previously
 * mentioned.<br>
 * If your check has dependencies you can declare them in the
62
63
64
65
66
67
68
69
 * {@link Check#getDependencies()} method. Be sure not to create cyclic
 * dependencies as that would result in undefined behavior.
 * 
 * @author Matthias Betz
 *
 */
public abstract class Check {

Matthias Betz's avatar
Matthias Betz committed
70
	private List<Class<Checkable>> applicableToClasses = new ArrayList<>(2);
71

Matthias Betz's avatar
Matthias Betz committed
72
	@SuppressWarnings("unchecked")
Matthias Betz's avatar
Matthias Betz committed
73
	protected Check() {
Matthias Betz's avatar
Matthias Betz committed
74
75
76
77
78
79
80
81
82
		Method[] declaredMethods = getClass().getDeclaredMethods();
		for (Method m : declaredMethods) {
			if ("check".equals(m.getName())) {
				Class<?>[] parameterTypes = m.getParameterTypes();
				if (parameterTypes.length == 1 && Checkable.class.isAssignableFrom(parameterTypes[0])) {
					applicableToClasses.add((Class<Checkable>) parameterTypes[0]);
				}
			}
		}
83
84
85
86
87
88
89
	}

	/**
	 * Returns all classes for which the check needs to be executed
	 * 
	 * @return a list of classes which the check applies to
	 */
Matthias Betz's avatar
Matthias Betz committed
90
91
92
	public List<Class<Checkable>> getApplicableToClasses() {
		return applicableToClasses;
	}
93
94
95
96
97
98
99
100
101
102
103

	/**
	 * A list of dependencies which the check depends on. Each of those dependencies
	 * needs to be executed and must have reported no error before this check can be
	 * executed.
	 * 
	 * @return a list of CheckIds which the check depends on.
	 */
	public List<CheckId> getDependencies() {
		return Collections.emptyList();
	}
104
105
	
	public abstract Set<Requirement> appliesToRequirements();
106
107
108
109
110
111

	/**
	 * Getter for the check id.
	 * 
	 * @return the check id.
	 */
Matthias Betz's avatar
Matthias Betz committed
112
	public abstract CheckId getCheckId();
113
114
115
116
117
118

	/**
	 * Getter for the check type.
	 * 
	 * @return the check type
	 */
119
	public abstract RequirementType getType();
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

	/**
	 * Checks whether the check can be executed on this checkable, meaning the
	 * checkable or its content can not have any error of any check dependent on
	 * this check. <br>
	 * If the check cannot be executed a CheckResult will be created with the
	 * ResultStatus = DEPENDENCIES_NOT_MET.
	 * 
	 * @param c   the checkable
	 * @param crc container for all check results
	 * @return true if the check can be executed, false if the checkable itself or
	 *         one of its containing checkables have an error.
	 */
	public boolean canExecute(Checkable c) {
		// ignore objects where this check doesn't apply to
135
		if (!canBeApplied(c)) {
136
137
138
139
140
141
142
			return false;
		}
		// check that object doesn't have errors for dependencies of this check
		for (CheckId dependencyCheck : getDependencies()) {
			boolean hasError = c.containsError(dependencyCheck);
			if (hasError) {
				// check whether a result was already inserted
Matthias Betz's avatar
Matthias Betz committed
143
				if (!c.hasDependencyNotMetError(getCheckId())) {
144
145
					// insert dependency error
					CheckError err = new DependenciesNotMetError(dependencyCheck);
Matthias Betz's avatar
Matthias Betz committed
146
					CheckResult cr = new CheckResult(getCheckId(), ResultStatus.DEPENDENCIES_NOT_MET, err);
147
148
149
150
151
152
153
					c.addCheckResult(cr);
				}
				return false;
			}
		}
		return true;
	}
Matthias Betz's avatar
Matthias Betz committed
154

155
156
157
158
159
160
161
162
	private boolean canBeApplied(Checkable c) {
		for (Class<Checkable> checkableClass : getApplicableToClasses()) {
			if (checkableClass.isAssignableFrom(c.getCheckClass())) {
				return true;
			}
		}
		return false;
	}
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

	/**
	 * check anything
	 * 
	 * @param checkable a checkable
	 */
	public void check(Checkable checkable) {

	}

	/**
	 * check buildings and building parts
	 * 
	 * @param ab building or building part
	 */
	public void check(AbstractBuilding ab) {

	}

	/**
	 * check boundary surfaces
	 * 
	 * @param bs a boundary surface
	 */
	public void check(BoundarySurface bs) {

	}

	/**
	 * check bridges
	 * 
	 * @param bo a bridge
	 */
	public void check(BridgeObject bo) {

	}

	/**
	 * check only buildings
	 * 
	 * @param b a building
	 */
	public void check(Building b) {

	}

	/**
	 * check building installations
	 * 
	 * @param bi a building installation
	 */
	public void check(BuildingInstallation bi) {

	}

	/**
	 * check only building parts
	 * 
	 * @param bp a building part
	 */
	public void check(BuildingPart bp) {

	}

	/**
	 * check all city objects
	 * 
	 * @param co a city object
	 */
	public void check(CityObject co) {

	}

	/**
	 * check land use objects
	 * 
	 * @param lo a land use object
	 */
	public void check(LandObject lo) {

	}

	/**
	 * check openings
	 * 
	 * @param o an opening
	 */
	public void check(Opening o) {

	}

	/**
	 * check transportation objects
	 * 
	 * @param to a transportation object
	 */
	public void check(TransportationObject to) {

	}

	/**
	 * check vegetation objects
	 * 
	 * @param veg a vegetation object
	 */
	public void check(Vegetation veg) {

	}

	/**
	 * check water objects
	 * 
	 * @param wo a water object
	 */
	public void check(WaterObject wo) {

	}

	/**
	 * check geometries
	 * 
	 * @param geom a geometry
	 */
	public void check(Geometry geom) {

	}

	/**
	 * check polygons
	 * 
	 * @param poly a polygon
	 */
	public void check(Polygon poly) {

	}

	/**
	 * check linear rings
	 * 
	 * @param ring a linear ring
	 */
	public void check(LinearRing ring) {

306
307
308
309
310
311
312
313
	}
	
	public void check(TinObject tin) {
		
	}
	
	public void check(ReliefObject relief) {
		
314
315
316
317
318
319
320
321
322
	}

	/**
	 * The initialization method of this check. It will be called before any check
	 * method will be executed. Override this if you want to have configurable
	 * parameters.
	 * 
	 * @param params the parameter map containing the parameters for the check in
	 *               String form. The key should be the same String provided by the
323
	 *               {@link Requirement#getDefaultParameter()} method
324
325
326
327
328
329
330
331
332
	 * @param config sometimes there are global parameters which can be used by
	 *               checks. Those are be stored in this container
	 */
	public void init(Map<String, String> params, ParserConfiguration config) {

	}

	@Override
	public String toString() {
Matthias Betz's avatar
Matthias Betz committed
333
		return "Check [id=" + getCheckId() + "]";
334
335
336
337
338
339
340
341
342
343
344
	}

	/**
	 * Create a new instance of this check. This is needed to keep the checks
	 * dynamic
	 * 
	 * @return a new instance of this check
	 */
	public abstract Check createNewInstance();

}