Gridarta Editor
ArtifactParser.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.artifact;
21 
22 import java.io.BufferedReader;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FilenameFilter;
26 import java.io.IOException;
27 import java.io.InputStreamReader;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.List;
42 import net.sf.gridarta.utils.IOUtils;
43 import org.apache.log4j.Category;
44 import org.apache.log4j.Logger;
45 import org.jetbrains.annotations.NotNull;
46 import org.jetbrains.annotations.Nullable;
47 
52 public class ArtifactParser<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
53 
57  @NotNull
58  private static final Category LOG = Logger.getLogger(ArtifactParser.class);
59 
63  @NotNull
65 
69  @NotNull
70  private final ErrorView errorView;
71 
75  @NotNull
77 
81  @NotNull
82  private final List<G> invObjects = new ArrayList<>();
83 
87  @NotNull
88  private final FilenameFilter artifactFilenameFilter = (dir, name) -> {
89  final File fullPath = new File(dir, name);
90  // TODO: Replace this with a proper FileFilter.
91  return fullPath.isDirectory() && !name.equalsIgnoreCase("cvs") && !name.equalsIgnoreCase(".xvpics") && !name.equalsIgnoreCase(".svn") || name.toLowerCase().endsWith(".art");
92  };
93 
101  this.archetypeSet = archetypeSet;
102  this.errorView = errorView;
103  this.archetypeParser = archetypeParser;
104  }
105 
110  @NotNull
111  public Collection<G> getInvObjects() {
112  return Collections.unmodifiableCollection(invObjects);
113  }
114 
125  public void loadArchesFromArtifacts(@NotNull final File f, @NotNull final String panelName, @NotNull final String folderName) {
126  final int archetypes = archetypeSet.getArchetypeCount();
127  loadArchesFromArtifactsRecursive(f, "", panelName, folderName);
128  if (LOG.isInfoEnabled()) {
129  LOG.info("Loaded " + (archetypeSet.getArchetypeCount() - archetypes) + " artifacts from '" + f + "'.");
130  }
131  }
132 
144  private void loadArchesFromArtifactsRecursive(@NotNull final File f, @NotNull final String archPath, @NotNull final String panelName, @NotNull final String folderName) {
145  if (f.isDirectory()) {
146  final String[] traverse = f.list(artifactFilenameFilter);
147  if (traverse != null) {
148  Arrays.sort(traverse);
149  for (final String entry : traverse) {
150  loadArchesFromArtifactsRecursive(new File(f, entry), archPath + "/" + entry, panelName, folderName);
151  }
152  }
153  } else {
154  loadArtifact(new ErrorViewCollector(errorView, f), f, archPath, panelName, folderName);
155  }
156  }
157 
168  private void loadArtifact(@NotNull final ErrorViewCollector errorViewCollector, @NotNull final File f, @NotNull final String archPath, @NotNull final String panelName, @NotNull final String folderName) {
169  try {
170  try (FileInputStream fis = new FileInputStream(f)) {
171  try (InputStreamReader isr = new InputStreamReader(fis, IOUtils.MAP_ENCODING)) {
172  try (BufferedReader in = new BufferedReader(isr)) {
173  loadArtifact(in, errorViewCollector, archPath, panelName, folderName);
174  }
175  }
176  }
177  } catch (final IOException ex) {
178  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_FILE_INVALID, ex.getMessage());
179  }
180  }
181 
191  public void loadArtifact(@NotNull final BufferedReader in, @NotNull final ErrorViewCollector errorViewCollector, @NotNull final String archPath, @NotNull final String panelName, @NotNull final String folderName) throws IOException {
192  int editorCode = -1;
193  @Nullable String name = null;
194  @Nullable String defArchName = null;
195  int lineCount = 0;
196 
197  @Nullable String editorPath = null;
198  while (true) {
199  final String thisLine2 = in.readLine();
200  if (thisLine2 == null) {
201  break;
202  }
203  lineCount++;
204  final String thisLine = thisLine2.trim();
205  // ignore white space lines or '#' comment lines
206  if (!thisLine.startsWith("#") && !thisLine.isEmpty()) {
207  if (thisLine.startsWith("artifact ")) {
208  name = thisLine.substring(9);
209  } else if (thisLine.startsWith("def_arch ")) {
210  defArchName = thisLine.substring(9);
211  } else if (thisLine.startsWith("editor ")) {
212  final String editor = thisLine.substring(7);
213  final int tIndex = editor.indexOf(':');
214  if (tIndex == -1) {
215  editorCode = Integer.parseInt(editor);
216  } else {
217  editorPath = editor.substring(tIndex + 1);
218  // TODO: use editorPath for determining the place of this GameObject
219  editorCode = Integer.parseInt(editor.substring(0, tIndex));
220  }
221  } else if (thisLine.startsWith("Object")) {
222  if (editorCode == -1) {
223  // TOOD: Warn user
224  }
225  if (editorCode == 0 || editorCode == 2/* || editorCode == -1 */) {
226  // TODO: read until "end"
227  }
228  final String objTitle = thisLine.length() > 7 ? thisLine.substring(7) : "";
229  // TODO: Allow not having a def arch
230  // at this point we MUST have a legal name and def arch
231  if (defArchName == null) {
232  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' has missing def_arch");
233  } else if (defArchName.isEmpty()) {
234  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' has empty def_arch");
235  } else if (name == null) {
236  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' has missing name");
237  } else if (name.isEmpty()) {
238  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' has empty name");
239  } else {
240  try {
241  final R archetype = archetypeSet.getArchetype(defArchName);
242  if (editorCode != 0 && editorCode != 2) { // the next line of our file is part of a arch parse until a "end" comes
243  // now the editor will do the same as the real server:
244  // get the default arch as base and parse the new values over it
245  // the extended functions of the artifacts file can be ignored here.
246  archetypeParser.parseArchetypeFromStream(in, editorCode == 2 ? null : archetype, thisLine, name, panelName, folderName, archPath, invObjects, errorViewCollector); // XXX: editorCode == 2 looks incorrect due to the enclosing condition editorCode != 2
247  // note: in the parser is a small part where we handle the title setting
248  // and the reverse type setting for type == -1 (unique items marker in artifacts file)
249  } else {
250  while (true) {
251  final String thisLine3 = in.readLine();
252  if (thisLine3 == null || thisLine3.equals("end")) {
253  break;
254  }
255  }
256  }
257  } catch (final UndefinedArchetypeException ex) {
258  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' references undefined archetype '" + ex.getMessage() + "'");
259  }
260  }
261  name = null;
262  defArchName = null;
263  editorPath = null;
264  editorCode = -1;
265  }
266  }
267  }
268  }
269 
270 }
name
name
Definition: ArchetypeTypeSetParserTest-ignoreDefaultAttribute1-result.txt:2
net.sf.gridarta.model.archetypeset.ArchetypeSet.getArchetype
R getArchetype(@NotNull String archetypeName)
Returns an Archetype by its name.
net.sf.gridarta.model.artifact.ArtifactParser.getInvObjects
Collection< G > getInvObjects()
Returns all collected inventory objects.
Definition: ArtifactParser.java:111
net.sf.gridarta
Base package of all Gridarta classes.
net.sf.gridarta.model.archetype.UndefinedArchetypeException
Exception thrown if an Archetype does not exist.
Definition: UndefinedArchetypeException.java:28
net.sf.gridarta.model.io.AbstractArchetypeParser
Abstract base implementation of ArchetypeParser.
Definition: AbstractArchetypeParser.java:47
net.sf
net.sf.gridarta.model.errorview.ErrorViewCategory.ARTIFACT_FILE_INVALID
ARTIFACT_FILE_INVALID
Definition: ErrorViewCategory.java:56
net.sf.gridarta.model.artifact.ArtifactParser.loadArtifact
void loadArtifact(@NotNull final ErrorViewCollector errorViewCollector, @NotNull final File f, @NotNull final String archPath, @NotNull final String panelName, @NotNull final String folderName)
Loads one artifact.
Definition: ArtifactParser.java:168
net.sf.gridarta.model.errorview.ErrorView
Interface for classes displaying error messages.
Definition: ErrorView.java:28
net.sf.gridarta.model.artifact.ArtifactParser
Parser for artifact definitions.
Definition: ArtifactParser.java:52
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.artifact.ArtifactParser.loadArchesFromArtifactsRecursive
void loadArchesFromArtifactsRecursive(@NotNull final File f, @NotNull final String archPath, @NotNull final String panelName, @NotNull final String folderName)
This method takes a filename or directory name as argument.
Definition: ArtifactParser.java:144
net.sf.gridarta.model.artifact.ArtifactParser.artifactFilenameFilter
final FilenameFilter artifactFilenameFilter
A FilenameFilter that matches "*.art" files.
Definition: ArtifactParser.java:88
net.sf.gridarta.model.artifact.ArtifactParser.errorView
final ErrorView errorView
The ErrorView for reporting errors.
Definition: ArtifactParser.java:70
net.sf.gridarta.model.gameobject
GameObjects are the objects based on Archetypes found on maps.
Definition: AbstractGameObject.java:20
net
net.sf.gridarta.model.errorview
Definition: ErrorView.java:20
net.sf.gridarta.model.archetypeset.ArchetypeSet.getArchetypeCount
int getArchetypeCount()
Returns the number of Archetypes available.
net.sf.gridarta.model.errorview.ErrorViewCollector
Convenience class for adding messages to a ErrorView instance using a fixed category name.
Definition: ErrorViewCollector.java:31
net.sf.gridarta.model.errorview.ErrorViewCategory
Defines possible error categories for ErrorView instances.
Definition: ErrorViewCategory.java:28
net.sf.gridarta.model.maparchobject.MapArchObject
Interface for MapArchObjects.
Definition: MapArchObject.java:40
net.sf.gridarta.model.artifact.ArtifactParser.archetypeSet
final ArchetypeSet< G, A, R > archetypeSet
The ArchetypeSet for looking up archetypes.
Definition: ArtifactParser.java:64
net.sf.gridarta.model.archetypeset.ArchetypeSet
Interface that captures similarities between different ArchetypeSet implementations.
Definition: ArchetypeSet.java:37
net.sf.gridarta.model.io
Reading and writing of maps, handling of paths.
Definition: AbstractAnimationObjectsReader.java:20
net.sf.gridarta.model.artifact.ArtifactParser.ArtifactParser
ArtifactParser(@NotNull final ArchetypeSet< G, A, R > archetypeSet, @NotNull final ErrorView errorView, @NotNull final AbstractArchetypeParser< G, A, R, ?> archetypeParser)
Creates a new instance.
Definition: ArtifactParser.java:100
net.sf.gridarta.model
net.sf.gridarta.model.archetype.Archetype
Reflects an Archetype.
Definition: Archetype.java:41
net.sf.gridarta.model.artifact.ArtifactParser.invObjects
final List< G > invObjects
Collects all inventory objects.
Definition: ArtifactParser.java:82
net.sf.gridarta.utils.IOUtils
Utility-class for Gridarta's I/O.
Definition: IOUtils.java:40
net.sf.gridarta.model.artifact.ArtifactParser.archetypeParser
final AbstractArchetypeParser< G, A, R, ?> archetypeParser
The AbstractArchetypeParser to use.
Definition: ArtifactParser.java:76
net.sf.gridarta.model.artifact.ArtifactParser.LOG
static final Category LOG
The logger for printing log messages.
Definition: ArtifactParser.java:58
editor
Daimonin Editor like your to identify any bugs in the editor
Definition: ReadMe.txt:5
net.sf.gridarta.model.maparchobject
Definition: AbstractMapArchObject.java:20
net.sf.gridarta.model.errorview.ErrorViewCategory.ARTIFACT_ENTRY_INVALID
ARTIFACT_ENTRY_INVALID
Definition: ErrorViewCategory.java:54
net.sf.gridarta.model.artifact.ArtifactParser.loadArchesFromArtifacts
void loadArchesFromArtifacts(@NotNull final File f, @NotNull final String panelName, @NotNull final String folderName)
This method takes a filename or directory name as argument.
Definition: ArtifactParser.java:125
net.sf.gridarta.model.archetypeset
Definition: ArchetypeSet.java:20
net.sf.gridarta.model.artifact.ArtifactParser.loadArtifact
void loadArtifact(@NotNull final BufferedReader in, @NotNull final ErrorViewCollector errorViewCollector, @NotNull final String archPath, @NotNull final String panelName, @NotNull final String folderName)
Loads one artifact.
Definition: ArtifactParser.java:191
net.sf.gridarta.model.io.AbstractArchetypeParser.parseArchetypeFromStream
void parseArchetypeFromStream(@NotNull final BufferedReader in, @Nullable final R prototype, @Nullable final String line, @Nullable final String archName, @NotNull final String panelName, @NotNull final String folderName, @NotNull final String archPath, @NotNull final List< G > invObjects, @NotNull final ErrorViewCollector errorViewCollector)
Definition: AbstractArchetypeParser.java:86
net.sf.gridarta.utils
Definition: ActionBuilderUtils.java:20
net.sf.gridarta.utils.IOUtils.MAP_ENCODING
static final String MAP_ENCODING
Encoding to use for maps and other data.
Definition: IOUtils.java:52