Gridarta Editor
ArchetypeAttributeParser.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 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.archetypetype;
21 
22 import java.util.regex.Pattern;
25 import nu.xom.Attribute;
26 import nu.xom.Element;
27 import nu.xom.Node;
28 import org.jetbrains.annotations.NotNull;
29 import org.jetbrains.annotations.Nullable;
30 
36 
40  @NotNull
41  private static final Pattern LINE_BREAK = Pattern.compile("\\s*\n\\s*");
42 
46  @NotNull
47  private static final Pattern UNDERSCORE = Pattern.compile("_");
48 
53  @NotNull
55 
60  public ArchetypeAttributeParser(@NotNull final ArchetypeAttributeFactory archetypeAttributeFactory) {
61  this.archetypeAttributeFactory = archetypeAttributeFactory;
62  }
63 
74  @Nullable
75  @SuppressWarnings("FeatureEnvy")
76  public ArchetypeAttribute load(@NotNull final Element attributeElement, @NotNull final ErrorViewCollector errorViewCollector, @NotNull final ArchetypeTypeSet archetypeTypeSet, @NotNull final String typeName) throws MissingAttributeException {
77  final String description = parseText(attributeElement);
78  final int inputLength = getAttributeIntValue(attributeElement, Constants.XML_ATTRIBUTE_LENGTH, 0, typeName, errorViewCollector);
79  final String attributeType = getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_TYPE);
80  if (attributeType.equals("bool")) {
81  return archetypeAttributeFactory.newArchetypeAttributeBool(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
82  } else if (attributeType.equals("bool_special")) {
83  return archetypeAttributeFactory.newArchetypeAttributeBoolSpec(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength, getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_TRUE), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_FALSE));
84  } else if (attributeType.equals("int")) {
85  final int minValue = getAttributeIntValue(attributeElement, Constants.XML_ATTRIBUTE_MIN, Integer.MIN_VALUE, typeName, errorViewCollector);
86  final int maxValue = getAttributeIntValue(attributeElement, Constants.XML_ATTRIBUTE_MAX, Integer.MAX_VALUE, typeName, errorViewCollector);
87  final int minCheckValue = getAttributeIntValue(attributeElement, Constants.XML_ATTRIBUTE_CHECK_MIN, minValue, typeName, errorViewCollector);
88  final int maxCheckValue = getAttributeIntValue(attributeElement, Constants.XML_ATTRIBUTE_CHECK_MAX, maxValue, typeName, errorViewCollector);
89 
90  if (minValue > maxValue) {
91  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + " has invalid " + Constants.XML_ATTRIBUTE_MIN + ".." + Constants.XML_ATTRIBUTE_MAX + " range: " + minValue + ".." + maxValue + ".");
92  return null;
93  }
94 
95  if (minCheckValue > maxCheckValue) {
96  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + " has invalid " + Constants.XML_ATTRIBUTE_CHECK_MIN + ".." + Constants.XML_ATTRIBUTE_CHECK_MAX + " range: " + minCheckValue + ".." + maxCheckValue + ".");
97  return null;
98  }
99 
100  if (minCheckValue < minValue) {
101  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + " has invalid " + Constants.XML_ATTRIBUTE_CHECK_MIN + " value: " + minCheckValue + " < " + Constants.XML_ATTRIBUTE_MIN + " = " + minValue + ".");
102  return null;
103  }
104 
105  if (maxCheckValue > maxValue) {
106  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + " has invalid " + Constants.XML_ATTRIBUTE_CHECK_MAX + " value: " + maxCheckValue + " > " + Constants.XML_ATTRIBUTE_MAX + " = " + maxValue + ".");
107  return null;
108  }
109 
110  return archetypeAttributeFactory.newArchetypeAttributeInt(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength, minValue, maxValue, minCheckValue, maxCheckValue);
111  } else if (attributeType.equals("long")) {
112  return archetypeAttributeFactory.newArchetypeAttributeLong(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
113  } else if (attributeType.equals("float")) {
114  return archetypeAttributeFactory.newArchetypeAttributeFloat(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
115  } else if (attributeType.equals("string")) {
116  return archetypeAttributeFactory.newArchetypeAttributeString(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
117  } else if (attributeType.equals("map_path")) {
118  return archetypeAttributeFactory.newArchetypeAttributeMapPath(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
119  } else if (attributeType.equals("script_file")) {
120  return archetypeAttributeFactory.newArchetypeAttributeScriptFile(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
121  } else if (attributeType.equals("facename")) {
122  return archetypeAttributeFactory.newArchetypeAttributeFacename(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
123  } else if (attributeType.equals("animname")) {
124  return archetypeAttributeFactory.newArchetypeAttributeAnimname(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
125  } else if (attributeType.equals("text")) {
126  return archetypeAttributeFactory.newArchetypeAttributeText(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH_BEGIN), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH_END), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength, getAttributeValueOptional(attributeElement, Constants.XML_ATTRIBUTE_MARKER));
127  } else if (attributeType.equals("fixed")) {
128  return archetypeAttributeFactory.newArchetypeAttributeFixed(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_VALUE), description, inputLength);
129  } else if (attributeType.equals("spell")) {
130  return archetypeAttributeFactory.newArchetypeAttributeSpell(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
131  } else if (attributeType.equals("nz_spell")) {
132  return archetypeAttributeFactory.newArchetypeAttributeZSpell(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
133  } else if (attributeType.equals("inv_spell")) {
134  return archetypeAttributeFactory.newArchetypeAttributeInvSpell(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
135  } else if (attributeType.equals("inv_spell_optional")) {
136  return archetypeAttributeFactory.newArchetypeAttributeInvSpellOptional(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
137  } else if (attributeType.startsWith("bitmask")) {
138  // got a bitmask attribute
139  final String bitmaskName = attributeType.substring(8).trim();
140  if (archetypeTypeSet.getBitmask(bitmaskName) == null) {
141  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + ": Bitmask \"" + bitmaskName + "\" is undefined.");
142  return null;
143  }
144  return archetypeAttributeFactory.newArchetypeAttributeBitmask(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength, bitmaskName);
145  } else if (attributeType.startsWith("list_")) {
146  // got a bitmask attribute
147  final String listName = attributeType.substring(5).trim();
148  if (archetypeTypeSet.getList(listName) == null) {
149  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + ": List \"" + listName + "\" is undefined.");
150  return null;
151  }
152  return archetypeAttributeFactory.newArchetypeAttributeList(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength, listName);
153  } else if (attributeType.startsWith("list2_")) {
154  // got a bitmask attribute
155  final String listNames = attributeType.substring(6).trim();
156  final String[] tmp = UNDERSCORE.split(listNames, 2);
157  if (tmp.length != 2) {
158  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + ": Lists \"" + listNames + "\" are undefined.");
159  return null;
160  }
161  final String listName1 = tmp[0];
162  final String listName2 = tmp[1];
163  if (archetypeTypeSet.getList(listName1) == null) {
164  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + ": List \"" + listName1 + "\" is undefined.");
165  return null;
166  }
167  if (archetypeTypeSet.getList(listName2) == null) {
168  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + ": List \"" + listName2 + "\" is undefined.");
169  return null;
170  }
171  return archetypeAttributeFactory.newArchetypeAttributeList2(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength, listName1, listName2);
172  } else if (attributeType.equals("treasurelist")) {
173  return archetypeAttributeFactory.newArchetypeAttributeTreasure(getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_ARCH), getAttributeValue(attributeElement, Constants.XML_ATTRIBUTE_EDITOR), description, inputLength);
174  } else {
175  // unknown type
176  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + " has an attribute with unknown type: '" + attributeType + "'.");
177  return null;
178  }
179  }
180 
188  @NotNull
189  private static String parseText(@NotNull final Node attributeElement) {
190  final String tmp = attributeElement.getValue().trim();
191  return LINE_BREAK.matcher(tmp).replaceAll(tmp.startsWith("<html>") ? " " : "\n");
192  }
193 
201  @NotNull
202  private static String getAttributeValue(@NotNull final Element element, @NotNull final String attributeKey) throws MissingAttributeException {
203  final Attribute attr = element.getAttribute(attributeKey);
204  if (attr == null) {
205  throw new MissingAttributeException(element.getLocalName(), attributeKey);
206  }
207 
208  return attr.getValue().trim();
209  }
210 
218  @Nullable
219  private static String getAttributeValueOptional(@NotNull final Element element, @NotNull final String attributeKey) {
220  final Attribute attr = element.getAttribute(attributeKey);
221  return attr == null ? null : attr.getValue().trim();
222  }
223 
234  private static int getAttributeIntValue(@NotNull final Element element, @NotNull final String attributeKey, final int defaultValue, @NotNull final String typeName, @NotNull final ErrorViewCollector errorViewCollector) {
235  final String value = getAttributeValueOptional(element, attributeKey);
236  if (value == null) {
237  return defaultValue;
238  }
239 
240  try {
241  return Integer.parseInt(value);
242  } catch (final NumberFormatException ignored) {
243  errorViewCollector.addWarning(ErrorViewCategory.TYPES_ENTRY_INVALID, "type " + typeName + " has attribute '" + attributeKey + "' with invalid value '" + value + "' (must be a number).");
244  }
245 
246  return defaultValue;
247  }
248 
249 }
Convenience class for adding messages to a ErrorView instance using a fixed category name...
static final String XML_ATTRIBUTE_CHECK_MIN
The name of the "check_min" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:278
ArchetypeAttribute load(@NotNull final Element attributeElement, @NotNull final ErrorViewCollector errorViewCollector, @NotNull final ArchetypeTypeSet archetypeTypeSet, @NotNull final String typeName)
Loading the data from an xml element into this object.
Interface for classes implementing ArchetypeAttribute factories.
Manages ArchetypeType instances, list, and bitmask definitions.
This Class contains the data of one archetype attribute.
ArchetypeAttribute newArchetypeAttributeInvSpellOptional(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "inv spell optional" archetype attribute.
static final Pattern LINE_BREAK
Pattern to match line breaks in attribute text.
static final String XML_ATTRIBUTE_MAX
The name of the "max" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:271
ArchetypeAttribute newArchetypeAttributeBitmask(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength, @NotNull String bitmaskName)
Creates a new "bitmask" archetype attribute.
static final String XML_ATTRIBUTE_ARCH_END
The name of the "arch_end" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:306
static String getAttributeValueOptional(@NotNull final Element element, @NotNull final String attributeKey)
Returns the value of an attribute.
ArchetypeAttribute newArchetypeAttributeAnimname(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "animname" archetype attribute.
An Exception thrown if an attribute key does not exist.
static final String XML_ATTRIBUTE_LENGTH
The name of the "length" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:313
ArchetypeAttribute newArchetypeAttributeList(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength, @NotNull String listName)
Creates a new "list" archetype attribute.
Constants needed to parse "types.xml" files.
Definition: Constants.java:28
static int getAttributeIntValue(@NotNull final Element element, @NotNull final String attributeKey, final int defaultValue, @NotNull final String typeName, @NotNull final ErrorViewCollector errorViewCollector)
Returns the value of an attribute as an.
static final String XML_ATTRIBUTE_EDITOR
The name of the "editor" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:250
static String parseText(@NotNull final Node attributeElement)
This method reads the text out of the element&#39;s "body" and cuts off white spaces at front/end of line...
Defines possible error categories for ErrorView instances.
ArchetypeAttribute newArchetypeAttributeText(@NotNull String archetypeAttributeName, @NotNull String endingOld, @NotNull String attributeName, @NotNull String description, int inputLength, @Nullable String fileExtension)
Creates a new "text" archetype attribute.
Base package of all Gridarta classes.
ArchetypeAttribute newArchetypeAttributeInvSpell(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "inv spell" archetype attribute.
static final String XML_ATTRIBUTE_TRUE
The name of the "true" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:320
ArchetypeAttribute newArchetypeAttributeBoolSpec(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength, @NotNull String trueValue, @NotNull String falseValue)
Creates a new "bool spec" archetype attribute.
ArchetypeAttribute newArchetypeAttributeInt(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength, int minValue, int maxValue, int minCheckValue, int maxCheckValue)
Creates a new "int" archetype attribute.
static final String XML_ATTRIBUTE_ARCH
The name of the "arch" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:243
static final String XML_ATTRIBUTE_TYPE
The name of the "type" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:292
static final String XML_ATTRIBUTE_FALSE
The name of the "false" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:327
static final Pattern UNDERSCORE
Pattern to match the list name separator in "list2_xxx_yyy" types.
ArchetypeAttribute newArchetypeAttributeSpell(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "spell" archetype attribute.
ArchetypeAttribute newArchetypeAttributeFacename(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "face name" archetype attribute.
static final String XML_ATTRIBUTE_CHECK_MAX
The name of the "check_max" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:285
ArchetypeAttribute newArchetypeAttributeZSpell(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "z-spell" archetype attribute.
ArchetypeAttribute newArchetypeAttributeTreasure(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "treasure" archetype attribute.
ArchetypeAttributeParser(@NotNull final ArchetypeAttributeFactory archetypeAttributeFactory)
Creates a new instance.
static final String XML_ATTRIBUTE_MIN
The name of the "min" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:264
ArchetypeAttribute newArchetypeAttributeMapPath(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "map path" archetype attribute.
static final String XML_ATTRIBUTE_VALUE
The name of the "value" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:257
static final String XML_ATTRIBUTE_MARKER
The name of the "marker" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:334
ArchetypeAttribute newArchetypeAttributeBool(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "bool" archetype attribute.
ArchetypeAttribute newArchetypeAttributeFixed(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "fixed" archetype attribute.
ArchetypeAttribute newArchetypeAttributeString(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "string" archetype attribute.
ArchetypeAttribute newArchetypeAttributeFloat(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "float" archetype attribute.
ArchetypeAttribute newArchetypeAttributeList2(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength, @NotNull String listName1, @NotNull String listName2)
Creates a new "list2" archetype attribute.
static final String XML_ATTRIBUTE_ARCH_BEGIN
The name of the "arch_begin" attribute within XML_ELEMENT_ATTRIBUTE elements.
Definition: Constants.java:299
final ArchetypeAttributeFactory archetypeAttributeFactory
The ArchetypeAttributeFactory for creating ArchetypeAttributes.
ArchetypeAttribute newArchetypeAttributeScriptFile(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "script file" archetype attribute.
static String getAttributeValue(@NotNull final Element element, @NotNull final String attributeKey)
Returns the value of an attribute.
ArchetypeAttribute newArchetypeAttributeLong(@NotNull String archetypeAttributeName, @NotNull String attributeName, @NotNull String description, int inputLength)
Creates a new "long" archetype attribute.