Gridarta Editor
GameObjectMatcherParser.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.match;
21 
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.Locale;
27 import nu.xom.Element;
28 import nu.xom.Node;
29 import nu.xom.Nodes;
30 import org.jetbrains.annotations.NotNull;
31 import org.jetbrains.annotations.Nullable;
32 
38 
43  @NotNull
44  private static final String XML_ATTRIB_ATTRIBUTE_NAME = "name";
45 
50  @NotNull
51  private static final String XML_ATTRIB_ATTRIBUTE_OP = "op";
52 
57  @NotNull
58  private static final String XML_ATTRIB_ATTRIBUTE_TYPE = "type";
59 
64  @NotNull
65  private static final String XML_ATTRIB_ATTRIBUTE_VALUE = "value";
66 
71  @NotNull
72  private static final String XML_ATTRIB_ATTRIBUTE_USEARCHETYPE = "useArchetype";
73 
77  @NotNull
78  private static final String XML_MATCHER_ATTRIBUTE_ID = "id";
79 
83  @NotNull
84  private static final String XML_MATCHER_ATTRIBUTE_SYSTEM = "system";
85 
89  @NotNull
90  private static final String XML_MATCHER_ELEMENT_ENV = "Env";
91 
95  @NotNull
96  private static final String XML_ELEMENT_TYPENRS = "TypeNrs";
97 
101  @NotNull
102  private static final String XML_ELEMENT_ATTRIB = "Attrib";
103 
107  @NotNull
108  private static final String XML_ELEMENT_OR = "Or";
109 
113  @NotNull
114  private static final String XML_ELEMENT_AND = "And";
115 
120  @NotNull
121  private static final String XML_TYPENRS_ATTRIBUTE_NUMBERS = "numbers";
122 
127  }
128 
136  @NotNull
137  public static NamedGameObjectMatcher parseMatcher(@NotNull final Element el, final int editType) throws ParsingException {
138  final String localName = el.getLocalName();
139  if (localName == null || !localName.equals("GameObjectMatcher")) {
140  throw new ParsingException("wrong local element name: expected \"GameObjectMatcher\" but got \"" + localName + "\"");
141  }
142  final String id = el.getAttribute(XML_MATCHER_ATTRIBUTE_ID).getValue();
143  String title = getLanguageTitle(el, Locale.getDefault().getLanguage());
144  if (title == null || title.isEmpty()) {
145  title = getLanguageTitle(el, "en");
146  }
147  if (title == null || title.isEmpty()) {
148  title = id;
149  }
150  final boolean systemMatcher = el.getAttribute(XML_MATCHER_ATTRIBUTE_SYSTEM).getValue().equals("true");
151  final Node content = xpathEvaluate(el, "*[last()]");
152  assert content != null;
153 
154  final Node env = xpathEvaluate(el, XML_MATCHER_ELEMENT_ENV);
155  @Nullable final GameObjectMatcher envGameObjectMatcher;
156  if (env instanceof Element) {
157  final Node envContent = xpathEvaluate(env, "*[1]");
158  envGameObjectMatcher = envContent == null ? new AndGameObjectMatcher(Collections.emptyList()) : createMatcher((Element) envContent);
159  } else {
160  envGameObjectMatcher = null;
161  }
162 
163  //XXX:assert content.getNodeType() == Node.ELEMENT_NODE;
164  final GameObjectMatcher matcher = createMatcher((Element) content);
165  return new NamedGameObjectMatcher(systemMatcher ? 0 : editType, id, title, systemMatcher, envGameObjectMatcher, matcher);
166  }
167 
174  @Nullable
175  private static String getLanguageTitle(@NotNull final Node el, @NotNull final String language) {
176  final Nodes nodes = el.query("title[lang('" + language + "')]");
177  return nodes.size() == 0 ? null : nodes.get(0).getValue();
178  }
179 
186  @NotNull
187  private static GameObjectMatcher createMatcher(@NotNull final Element el) throws ParsingException {
188  final String localName = el.getLocalName();
189  if (localName == null) {
190  // ignore
191  } else if (localName.equals(XML_ELEMENT_TYPENRS)) {
193  } else if (localName.equals(XML_ELEMENT_ATTRIB)) {
195  } else if (localName.equals(XML_ELEMENT_OR)) {
196  return createOrMatcher(el);
197  } else if (localName.equals(XML_ELEMENT_AND)) {
198  return createAndMatcher(el);
199  }
200  throw new ParsingException("expected element node name to be one of \"" + XML_ELEMENT_TYPENRS + "\", \"" + XML_ELEMENT_ATTRIB + "\", \"" + XML_ELEMENT_OR + "\", \"" + XML_ELEMENT_AND + "\".");
201  }
202 
209  @NotNull
210  private static GameObjectMatcher createAndMatcher(@NotNull final Node el) throws ParsingException {
211  return new AndGameObjectMatcher(getChildMatchers(el));
212  }
213 
220  @NotNull
221  private static GameObjectMatcher createOrMatcher(@NotNull final Node el) throws ParsingException {
222  return new OrGameObjectMatcher(getChildMatchers(el));
223  }
224 
234  @NotNull
235  private static Collection<GameObjectMatcher> getChildMatchers(@NotNull final Node el) throws ParsingException {
236  final Collection<GameObjectMatcher> childMatchers = new ArrayList<>();
237  for (int i = 0; i < el.getChildCount(); i++) {
238  final Node childNode = el.getChild(i);
239  if (childNode instanceof Element) {
240  childMatchers.add(createMatcher((Element) childNode));
241  }
242  }
243  return childMatchers;
244  }
245 
252  @NotNull
253  private static GameObjectMatcher createAttributeArchObjectMatcher(@NotNull final Element el) throws ParsingException {
254  final String type = el.getAttribute(XML_ATTRIB_ATTRIBUTE_TYPE).getValue();
255  if (type.equals("string")) {
256  return new StringAttributeGameObjectMatcher(el.getAttribute(XML_ATTRIB_ATTRIBUTE_NAME).getValue(), Enum.valueOf(Operation.class, el.getAttribute(XML_ATTRIB_ATTRIBUTE_OP).getValue()), el.getAttribute(XML_ATTRIB_ATTRIBUTE_VALUE).getValue(), el.getAttribute(XML_ATTRIB_ATTRIBUTE_USEARCHETYPE).getValue().equals("true"));
257  }
258  if (type.equals("int")) {
259  return new IntAttributeGameObjectMatcher(el.getAttribute(XML_ATTRIB_ATTRIBUTE_NAME).getValue(), Enum.valueOf(Operation.class, el.getAttribute(XML_ATTRIB_ATTRIBUTE_OP).getValue()), el.getAttribute(XML_ATTRIB_ATTRIBUTE_VALUE).getValue(), el.getAttribute(XML_ATTRIB_ATTRIBUTE_USEARCHETYPE).getValue().equals("true"));
260  }
261  throw new AssertionError("impossible value '" + type + "' for XML_ATTRIB_ATTRIBUTE_TYPE");
262  }
263 
270  @NotNull
271  private static GameObjectMatcher createTypeNrsArchObjectMatcher(@NotNull final Element el) throws ParsingException {
272  final CharSequence numbers = el.getAttribute(XML_TYPENRS_ATTRIBUTE_NUMBERS).getValue();
273  final String[] typeNrs = StringUtils.PATTERN_WHITESPACE.split(numbers, 0);
274  final int[] types = new int[typeNrs.length];
275  for (int i = 0; i < types.length; i++) {
276  try {
277  types[i] = Integer.parseInt(typeNrs[i]);
278  } catch (final NumberFormatException ex) {
279  throw new ParsingException("invalid number: " + typeNrs[i], ex);
280  }
281  }
282  return new TypeNrsGameObjectMatcher(types);
283  }
284 
291  @Nullable
292  private static Node xpathEvaluate(@NotNull final Node el, @NotNull final String xpathExpression) {
293  final Nodes nodes = el.query(xpathExpression);
294  assert nodes.size() <= 1;
295  return nodes.size() == 0 ? null : nodes.get(0);
296  }
297 
298 }
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_ATTRIB_ATTRIBUTE_NAME
static final String XML_ATTRIB_ATTRIBUTE_NAME
The name of the "name" attribute within XML_ELEMENT_ATTRIB elements.
Definition: GameObjectMatcherParser.java:44
net.sf.gridarta
Base package of all Gridarta classes.
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_MATCHER_ATTRIBUTE_SYSTEM
static final String XML_MATCHER_ATTRIBUTE_SYSTEM
The name of the "system" attribute within matcher elements.
Definition: GameObjectMatcherParser.java:84
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_ATTRIB_ATTRIBUTE_TYPE
static final String XML_ATTRIB_ATTRIBUTE_TYPE
The name of the "type" attribute within XML_ELEMENT_ATTRIB elements.
Definition: GameObjectMatcherParser.java:58
net.sf.gridarta.model.match.GameObjectMatcherParser
Class for some default GameObjectMatchers.
Definition: GameObjectMatcherParser.java:37
net.sf
net.sf.gridarta.model.match.GameObjectMatcherParser.createOrMatcher
static GameObjectMatcher createOrMatcher(@NotNull final Node el)
Creates an OrGameObjectMatcher.
Definition: GameObjectMatcherParser.java:221
net.sf.gridarta.model.match.GameObjectMatcherParser.GameObjectMatcherParser
GameObjectMatcherParser()
Private constructor to prevent instantiation.
Definition: GameObjectMatcherParser.java:126
net.sf.gridarta.model.match.GameObjectMatcherParser.getLanguageTitle
static String getLanguageTitle(@NotNull final Node el, @NotNull final String language)
Returns the title for a given language.
Definition: GameObjectMatcherParser.java:175
net.sf.gridarta.model.match.GameObjectMatcher
Interface for classes that match GameObjects.
Definition: GameObjectMatcher.java:30
net.sf.gridarta.model.match.IntAttributeGameObjectMatcher
A AttributeGameObjectMatcher that compares attributes values using "int" type.
Definition: IntAttributeGameObjectMatcher.java:30
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_ATTRIB_ATTRIBUTE_USEARCHETYPE
static final String XML_ATTRIB_ATTRIBUTE_USEARCHETYPE
The name of the "useArchetype" attribute within {} elements.
Definition: GameObjectMatcherParser.java:72
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_ELEMENT_AND
static final String XML_ELEMENT_AND
The name of the "And" element.
Definition: GameObjectMatcherParser.java:114
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.match.GameObjectMatcherParser.xpathEvaluate
static Node xpathEvaluate(@NotNull final Node el, @NotNull final String xpathExpression)
Evaluates an XPath expression and returns the result Node.
Definition: GameObjectMatcherParser.java:292
net.sf.gridarta.model.match.Operation
Operator.
Definition: Operation.java:27
net.sf.gridarta.model.match.NamedGameObjectMatcher
Decorates an arbitrary GameObjectMatcher with a localized name that is suitable for the user interfac...
Definition: NamedGameObjectMatcher.java:33
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_MATCHER_ATTRIBUTE_ID
static final String XML_MATCHER_ATTRIBUTE_ID
The name of the "id" attribute within matcher elements.
Definition: GameObjectMatcherParser.java:78
net
net.sf.gridarta.model.match.TypeNrsGameObjectMatcher
An GameObjectMatcher matching certain archetype types.
Definition: TypeNrsGameObjectMatcher.java:30
net.sf.gridarta.model.match.GameObjectMatcherParser.createMatcher
static GameObjectMatcher createMatcher(@NotNull final Element el)
Creates a GameObjectMatcher from XML.
Definition: GameObjectMatcherParser.java:187
net.sf.gridarta.model.match.AndGameObjectMatcher
A GameObjectMatcher that And-combines other.
Definition: AndGameObjectMatcher.java:32
net.sf.gridarta.model.match.StringAttributeGameObjectMatcher
A AttributeGameObjectMatcher that compares attributes values using "string" type.
Definition: StringAttributeGameObjectMatcher.java:30
net.sf.gridarta.model.match.GameObjectMatcherParser.parseMatcher
static NamedGameObjectMatcher parseMatcher(@NotNull final Element el, final int editType)
Creates a NamedGameObjectMatcher from XML.
Definition: GameObjectMatcherParser.java:137
net.sf.gridarta.model.match.GameObjectMatcherParser.createTypeNrsArchObjectMatcher
static GameObjectMatcher createTypeNrsArchObjectMatcher(@NotNull final Element el)
Creates a TypeNrsGameObjectMatcher.
Definition: GameObjectMatcherParser.java:271
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_ELEMENT_OR
static final String XML_ELEMENT_OR
The name of the "Or" element.
Definition: GameObjectMatcherParser.java:108
net.sf.gridarta.utils.StringUtils
Utility class for string manipulation.
Definition: StringUtils.java:31
net.sf.gridarta.model.match.ParsingException
Thrown when a parsing error occurs.
Definition: ParsingException.java:29
net.sf.gridarta.model.match.GameObjectMatcherParser.createAndMatcher
static GameObjectMatcher createAndMatcher(@NotNull final Node el)
Creates an AndGameObjectMatcher.
Definition: GameObjectMatcherParser.java:210
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_MATCHER_ELEMENT_ENV
static final String XML_MATCHER_ELEMENT_ENV
The name of the "Env" element within matcher elements.
Definition: GameObjectMatcherParser.java:90
net.sf.gridarta.model.match.OrGameObjectMatcher
A GameObjectMatcher that Or-combines other.
Definition: OrGameObjectMatcher.java:32
net.sf.gridarta.model.match.GameObjectMatcherParser.createAttributeArchObjectMatcher
static GameObjectMatcher createAttributeArchObjectMatcher(@NotNull final Element el)
Creates an AttributeGameObjectMatcher.
Definition: GameObjectMatcherParser.java:253
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_TYPENRS_ATTRIBUTE_NUMBERS
static final String XML_TYPENRS_ATTRIBUTE_NUMBERS
The name of the "numbers" attribute within XML_ELEMENT_TYPENRS elements.
Definition: GameObjectMatcherParser.java:121
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_ELEMENT_ATTRIB
static final String XML_ELEMENT_ATTRIB
The name of the "Attrib" element.
Definition: GameObjectMatcherParser.java:102
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_ATTRIB_ATTRIBUTE_OP
static final String XML_ATTRIB_ATTRIBUTE_OP
The name of the "op" attribute within XML_ELEMENT_ATTRIB elements.
Definition: GameObjectMatcherParser.java:51
net.sf.gridarta.utils
Definition: ActionBuilderUtils.java:20
net.sf.gridarta.model.match.GameObjectMatcherParser.getChildMatchers
static Collection< GameObjectMatcher > getChildMatchers(@NotNull final Node el)
Gets the matchers that are found as children of an XML element.
Definition: GameObjectMatcherParser.java:235
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_ATTRIB_ATTRIBUTE_VALUE
static final String XML_ATTRIB_ATTRIBUTE_VALUE
The name of the "value" attribute within XML_ELEMENT_ATTRIB elements.
Definition: GameObjectMatcherParser.java:65
net.sf.gridarta.model.match.GameObjectMatcherParser.XML_ELEMENT_TYPENRS
static final String XML_ELEMENT_TYPENRS
The name of the "TypeNrs" element.
Definition: GameObjectMatcherParser.java:96