Gridarta Editor
ValidatorFactory.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2023 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.model.validation.checks;
21 
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.InvocationTargetException;
24 import java.util.regex.Pattern;
25 import java.util.regex.PatternSyntaxException;
40 import org.jetbrains.annotations.NotNull;
41 
48 public class ValidatorFactory<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
49 
54  @NotNull
56 
61  @NotNull
63 
68  @NotNull
70 
75  @NotNull
77 
82  @NotNull
84 
99  this.validatorPreferences = validatorPreferences;
100  this.gameObjectMatchers = gameObjectMatchers;
101  this.projectSettings = projectSettings;
102  this.mapWriter = mapWriter;
103  this.mapManager = mapManager;
104  }
105 
112  @NotNull
113  @SuppressWarnings("ChainOfInstanceofChecks")
114  public Validator<G, A, R> newValidator(@NotNull final CharSequence spec) throws NoSuchValidatorException {
115  final String[] args = StringUtils.PATTERN_WHITESPACE.split(spec);
116  final Class<?> tmpClass;
117  //noinspection ErrorNotRethrown
118  try {
119  tmpClass = Class.forName(args[0]);
120  } catch (final ClassNotFoundException | LinkageError ex) {
121  throw new NoSuchValidatorException("class " + args[0] + " does not exist", ex);
122  }
123  final Class<?> classValidator;
124  try {
125  classValidator = tmpClass.asSubclass(Validator.class);
126  } catch (final ClassCastException ex) {
127  throw new NoSuchValidatorException("class " + args[0] + " does not exist", ex);
128  }
129  final Constructor<?>[] constructors = classValidator.getConstructors();
130  if (constructors.length == 0) {
131  throw new NoSuchValidatorException("class " + args[0] + " has no public constructors");
132  }
133  if (constructors.length > 1) {
134  throw new NoSuchValidatorException("class " + args[0] + " has more than one public constructor");
135  }
136  //Class.getConstructors() did return the wrong type
137  @SuppressWarnings("unchecked") final Constructor<? extends Validator<G, A, R>> constructor = (Constructor<? extends Validator<G, A, R>>) constructors[0];
138  final Class<?>[] constructorParameterTypes = constructor.getParameterTypes();
139  final Object[] constructorArguments = new Object[constructorParameterTypes.length];
140  int pos = 1;
141  for (int i = 0; i < constructorParameterTypes.length; i++) {
142  final Class<?> constructorParameterType = constructorParameterTypes[i];
143  if (constructorParameterType == ValidatorPreferences.class) {
144  constructorArguments[i] = validatorPreferences;
145  } else if (constructorParameterType == ProjectSettings.class) {
146  constructorArguments[i] = projectSettings;
147  } else if (constructorParameterType == MapWriter.class) {
148  constructorArguments[i] = mapWriter;
149  } else if (constructorParameterType == MapManager.class) {
150  constructorArguments[i] = mapManager;
151  } else {
152  if (pos >= args.length) {
153  throw new NoSuchValidatorException("missing argument in '" + spec + "'");
154  }
155  final String arg = args[pos++];
156  if (constructorParameterType == Integer[].class) {
157  constructorArguments[i] = createIntegerArray(arg);
158  } else if (constructorParameterType == GameObjectMatcher.class) {
159  constructorArguments[i] = createGameObjectMatcher(arg);
160  } else if (constructorParameterType == int.class) {
161  constructorArguments[i] = createInteger(arg);
162  } else if (constructorParameterType == String[].class) {
163  constructorArguments[i] = createStringArray(args, pos - 1);
164  pos = args.length;
165  } else if (constructorParameterType == Pattern.class) {
166  constructorArguments[i] = createPattern(arg);
167  } else {
168  throw new NoSuchValidatorException("class " + args[0] + "'s constructor requires a parameter of type " + constructorParameterType.getName() + "; this type is not supported");
169  }
170  }
171  }
172  final Validator<G, A, R> validator;
173  //noinspection ErrorNotRethrown
174  try {
175  validator = constructor.newInstance(constructorArguments);
176  } catch (final ExceptionInInitializerError ex) {
177  throw new NoSuchValidatorException("cannot initialize class " + args[0], ex);
178  } catch (final InstantiationException ex) {
179  throw new NoSuchValidatorException("class " + args[0] + " is abstract", ex);
180  } catch (final IllegalAccessException | IllegalArgumentException ex) {
181  throw new AssertionError(ex);
182  } catch (final InvocationTargetException ex) {
183  throw new NoSuchValidatorException("cannot instantiate class " + args[0], ex);
184  }
185  if (pos < args.length) {
186  if (classValidator == UnsetSlayingChecker.class) {
187  final UnsetSlayingChecker<?, ?, ?> unsetSlayingChecker = (UnsetSlayingChecker<?, ?, ?>) validator;
188  do {
189  unsetSlayingChecker.addAllowedValue(args[pos]);
190  pos++;
191  } while (pos < args.length);
192  } else if (classValidator == CustomTypeChecker.class) {
193  final CustomTypeChecker<?, ?, ?> customTypeChecker = (CustomTypeChecker<?, ?, ?>) validator;
194  do {
195  final String[] tmp = StringUtils.PATTERN_COMMA.split(args[pos], -1);
196  if (tmp.length != 2 && tmp.length != 3) {
197  throw new NoSuchValidatorException("invalid from,to or from,to,env type: " + args[pos]);
198  }
199  final int fromType;
200  try {
201  fromType = Integer.parseInt(tmp[0]);
202  } catch (final NumberFormatException ex) {
203  throw new NoSuchValidatorException("invalid from type: " + args[pos], ex);
204  }
205  final int toType;
206  try {
207  toType = Integer.parseInt(tmp[1]);
208  } catch (final NumberFormatException ex) {
209  throw new NoSuchValidatorException("invalid to type: " + args[pos], ex);
210  }
211  if (tmp.length == 2) {
212  customTypeChecker.addIgnore(fromType, toType);
213  } else {
214  final int envType;
215  try {
216  envType = Integer.parseInt(tmp[2]);
217  } catch (final NumberFormatException ex) {
218  throw new NoSuchValidatorException("invalid env type: " + args[pos], ex);
219  }
220  customTypeChecker.addIgnore(fromType, toType, envType);
221  }
222  pos++;
223  } while (pos < args.length);
224  } else if (classValidator == SlayingChecker.class) {
225  final SlayingChecker<?, ?, ?> slayingChecker = (SlayingChecker<?, ?, ?>) validator;
226  do {
227  final String[] tmp = StringUtils.PATTERN_COMMA.split(args[pos], 2);
228  if (tmp.length != 2) {
229  throw new NoSuchValidatorException("invalid matcher,pattern: " + args[pos]);
230  }
231  final GameObjectMatcher matcher = createGameObjectMatcher(tmp[0]);
232  final Pattern pattern = createPattern(tmp[1]);
233  slayingChecker.addMatcher(matcher, pattern);
234  pos++;
235  } while (pos < args.length);
236  } else {
237  throw new NoSuchValidatorException("excess arguments for '" + spec + "'");
238  }
239  }
240  return validator;
241  }
242 
250  @NotNull
251  private static Integer @NotNull [] createIntegerArray(@NotNull final CharSequence arg) throws NoSuchValidatorException {
252  final String[] tmp = StringUtils.PATTERN_COMMA.split(arg, -1);
253  final Integer[] result = new Integer[tmp.length];
254  for (int i = 0; i < tmp.length; i++) {
255  try {
256  result[i] = Integer.parseInt(tmp[i]);
257  } catch (final NumberFormatException ex) {
258  throw new NoSuchValidatorException("not a number: " + tmp[i], ex);
259  }
260  }
261  return result;
262  }
263 
272  @NotNull
273  private String @NotNull [] createStringArray(@NotNull final String @NotNull [] args, final int pos) throws NoSuchValidatorException {
274  final StringParameterBuilder stringParameterBuilder = new StringParameterBuilder();
275  stringParameterBuilder.addParameter("COLLECTED", projectSettings.getCollectedDirectory().getPath());
276  stringParameterBuilder.addParameter("ARCH", projectSettings.getArchDirectory().getPath());
277  stringParameterBuilder.addParameter("MAPS", projectSettings.getMapsDirectory().getPath());
278  stringParameterBuilder.addParameter("MAP", MapCheckerScriptChecker.MAP_PLACEHOLDER);
279  stringParameterBuilder.addParameter("REAL_MAP", MapCheckerScriptChecker.REAL_MAP_PLACEHOLDER);
280  final String[] result = new String[args.length - pos];
281  for (int i = 0; i < result.length; i++) {
282  try {
283  result[i] = stringParameterBuilder.replace(args[pos + i]);
284  } catch (final SyntaxErrorException ex) {
285  throw new NoSuchValidatorException(ex.getMessage(), ex);
286  }
287  }
288  return result;
289  }
290 
298  @NotNull
299  private GameObjectMatcher createGameObjectMatcher(@NotNull final String arg) throws NoSuchValidatorException {
300  final GameObjectMatcher gameObjectMatcher = gameObjectMatchers.getMatcher(arg);
301  if (gameObjectMatcher == null) {
302  throw new NoSuchValidatorException("undefined game object matcher: " + arg);
303  }
304  return gameObjectMatcher;
305  }
306 
314  @NotNull
315  private static Integer createInteger(@NotNull final String arg) throws NoSuchValidatorException {
316  try {
317  return Integer.parseInt(arg);
318  } catch (final NumberFormatException ex) {
319  throw new NoSuchValidatorException("invalid number: " + arg, ex);
320  }
321  }
322 
330  @NotNull
331  private static Pattern createPattern(@NotNull final String arg) throws NoSuchValidatorException {
332  try {
333  return Pattern.compile(arg);
334  } catch (final PatternSyntaxException ex) {
335  throw new NoSuchValidatorException("invalid pattern: " + arg, ex);
336  }
337  }
338 
339 }
net.sf.gridarta.model.mapmanager
Definition: AbstractMapManager.java:20
net.sf.gridarta.model.validation.checks.ValidatorFactory.gameObjectMatchers
final GameObjectMatchers gameObjectMatchers
The GameObjectMatchers for looking up GameObjectMatcher instances from string representation.
Definition: ValidatorFactory.java:62
net.sf.gridarta.model.validation.checks.ValidatorFactory.createPattern
static Pattern createPattern(@NotNull final String arg)
Creates an.
Definition: ValidatorFactory.java:331
net.sf.gridarta.model.mapmanager.MapManager
A MapManager manages all opened maps.
Definition: MapManager.java:37
net.sf.gridarta.model.validation.checks.MapCheckerScriptChecker.REAL_MAP_PLACEHOLDER
static final String REAL_MAP_PLACEHOLDER
The placeholder in the command's arguments for the real map path.
Definition: MapCheckerScriptChecker.java:79
net.sf.gridarta.utils.StringParameterBuilder.replace
String replace(@NotNull final CharSequence spec)
Replaces all parameters in a string.
Definition: StringParameterBuilder.java:64
net.sf.gridarta
Base package of all Gridarta classes.
net.sf.gridarta.model.validation.checks.ValidatorFactory.validatorPreferences
final ValidatorPreferences validatorPreferences
The ValidatorPreferences to pass to the newly created {} instances.
Definition: ValidatorFactory.java:55
net.sf.gridarta.model.validation.checks.ValidatorFactory.createStringArray
String[] createStringArray(@NotNull final String @NotNull[] args, final int pos)
Creates an.
Definition: ValidatorFactory.java:273
net.sf.gridarta.model.validation.checks.MapCheckerScriptChecker.MAP_PLACEHOLDER
static final String MAP_PLACEHOLDER
The placeholder in the command's arguments for the map to check.
Definition: MapCheckerScriptChecker.java:67
net.sf.gridarta.utils.StringParameterBuilder
Replaces placeholders in strings.
Definition: StringParameterBuilder.java:32
net.sf.gridarta.model.validation.checks.CustomTypeChecker.addIgnore
void addIgnore(final int fromType, final int toType)
Adds an allowed type change.
Definition: CustomTypeChecker.java:98
net.sf
net.sf.gridarta.model.validation.checks.ValidatorFactory.createInteger
static Integer createInteger(@NotNull final String arg)
Creates an.
Definition: ValidatorFactory.java:315
net.sf.gridarta.model.match.GameObjectMatcher
Interface for classes that match GameObjects.
Definition: GameObjectMatcher.java:30
net.sf.gridarta.model.archetype
Definition: AbstractArchetype.java:20
net.sf.gridarta.model.gameobject.GameObject
Reflects a game object (object on a map).
Definition: GameObject.java:36
net.sf.gridarta.model.validation.Validator
Super-interface for validators.
Definition: Validator.java:31
net.sf.gridarta.model.match.GameObjectMatchers.getMatcher
GameObjectMatcher getMatcher(@NotNull final String... ids)
Returns a matcher by id; returns.
Definition: GameObjectMatchers.java:68
net.sf.gridarta.utils.StringUtils.PATTERN_WHITESPACE
static final Pattern PATTERN_WHITESPACE
Pattern to match whitespace excluding NL and CR.
Definition: StringUtils.java:37
net.sf.gridarta.model.validation.checks.ValidatorFactory.createIntegerArray
static Integer[] createIntegerArray(@NotNull final CharSequence arg)
Creates an.
Definition: ValidatorFactory.java:251
net.sf.gridarta.model.validation.checks.UnsetSlayingChecker.addAllowedValue
void addAllowedValue(@NotNull final String value)
Adds a value which does not trigger a warning.
Definition: UnsetSlayingChecker.java:69
net.sf.gridarta.model.validation.ValidatorPreferences
Configuration parameters for Validators.
Definition: ValidatorPreferences.java:28
net.sf.gridarta.model.gameobject
GameObjects are the objects based on Archetypes found on maps.
Definition: AbstractGameObject.java:20
net
net.sf.gridarta.model.validation.checks.ValidatorFactory.mapManager
final MapManager< G, A, R > mapManager
The MapManager to pass to the newly created Validator instances.
Definition: ValidatorFactory.java:83
net.sf.gridarta.model.io.MapWriter
Interface for classes that write map files.
Definition: MapWriter.java:34
net.sf.gridarta.model.validation.NoSuchValidatorException
Exception thrown if a map validator cannot be created.
Definition: NoSuchValidatorException.java:28
net.sf.gridarta.model.match
Classes related to matching {GameObjects}, so called { net.sf.gridarta.model.match....
Definition: AndGameObjectMatcher.java:20
net.sf.gridarta.model.maparchobject.MapArchObject
Interface for MapArchObjects.
Definition: MapArchObject.java:40
net.sf.gridarta.model.match.GameObjectMatchers
Maintains GameObjectMatcher instances.
Definition: GameObjectMatchers.java:40
net.sf.gridarta.model.validation.checks.MapCheckerScriptChecker
Executes a script to check a map.
Definition: MapCheckerScriptChecker.java:55
net.sf.gridarta.model.validation.checks.ValidatorFactory.ValidatorFactory
ValidatorFactory(@NotNull final ValidatorPreferences validatorPreferences, @NotNull final GameObjectMatchers gameObjectMatchers, @NotNull final ProjectSettings projectSettings, @NotNull final MapWriter< G, A, R > mapWriter, @NotNull final MapManager< G, A, R > mapManager)
Creates a new instance.
Definition: ValidatorFactory.java:98
net.sf.gridarta.model.validation
This package contains the framework for validating maps.
Definition: AbstractValidator.java:20
net.sf.gridarta.utils.StringParameterBuilder.addParameter
void addParameter(@NotNull final String key, @NotNull final String value)
Adds a parameter key/value pair.
Definition: StringParameterBuilder.java:53
net.sf.gridarta.model.validation.checks.UnsetSlayingChecker
Checks that a game object does not set a custom type.
Definition: UnsetSlayingChecker.java:40
net.sf.gridarta.utils.StringUtils
Utility class for string manipulation.
Definition: StringUtils.java:31
net.sf.gridarta.model.io
Reading and writing of maps, handling of paths.
Definition: AbstractAnimationObjectsReader.java:20
net.sf.gridarta.model.settings.ProjectSettings
Settings that apply to a project.
Definition: ProjectSettings.java:29
net.sf.gridarta.model.validation.checks.ValidatorFactory.newValidator
Validator< G, A, R > newValidator(@NotNull final CharSequence spec)
Creates a new Validator instance from string representation.
Definition: ValidatorFactory.java:114
net.sf.gridarta.model.validation.checks.ValidatorFactory.mapWriter
final MapWriter< G, A, R > mapWriter
The MapWriter to pass to the newly created Validator instances.
Definition: ValidatorFactory.java:76
net.sf.gridarta.utils.SyntaxErrorException
Exception thrown for incorrect arguments.
Definition: SyntaxErrorException.java:28
net.sf.gridarta.model.validation.checks.SlayingChecker.addMatcher
void addMatcher(@NotNull final GameObjectMatcher gameObjectMatcher, @NotNull final Pattern regex)
Adds a matcher to check.
Definition: SlayingChecker.java:73
net.sf.gridarta.utils.StringUtils.PATTERN_COMMA
static final Pattern PATTERN_COMMA
The pattern that matches a single comma (",").
Definition: StringUtils.java:97
net.sf.gridarta.model
net.sf.gridarta.model.archetype.Archetype
Reflects an Archetype.
Definition: Archetype.java:41
net.sf.gridarta.model.settings.ProjectSettings.getArchDirectory
File getArchDirectory()
Returns the archetype directory.
net.sf.gridarta.model.settings.ProjectSettings.getCollectedDirectory
File getCollectedDirectory()
Returns the directory where collected archetypes are stored.
net.sf.gridarta.model.maparchobject
Definition: AbstractMapArchObject.java:20
net.sf.gridarta.model.validation.checks.ValidatorFactory
A factory for creating Validator instances from string representation.
Definition: ValidatorFactory.java:48
net.sf.gridarta.model.settings.ProjectSettings.getMapsDirectory
File getMapsDirectory()
Returns the default maps directory.
net.sf.gridarta.model.validation.checks.ValidatorFactory.createGameObjectMatcher
GameObjectMatcher createGameObjectMatcher(@NotNull final String arg)
Creates a GameObjectMatcher instance from string representation.
Definition: ValidatorFactory.java:299
net.sf.gridarta.model.validation.checks.SlayingChecker
A GameObjectValidator to assert that game objects do not have critical slaying strings.
Definition: SlayingChecker.java:42
net.sf.gridarta.utils
Definition: ActionBuilderUtils.java:20
net.sf.gridarta.model.validation.checks.ValidatorFactory.projectSettings
final ProjectSettings projectSettings
The ProjectSettings to pass to the newly created {} instances.
Definition: ValidatorFactory.java:69
net.sf.gridarta.model.settings
Definition: AbstractDefaultProjectSettings.java:20
net.sf.gridarta.model.validation.checks.CustomTypeChecker
Checks that a game object does not set a custom type.
Definition: CustomTypeChecker.java:39