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-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.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 = new FilenameFilter() {
89 
90  @Override
91  public boolean accept(final File dir, final String name) {
92  final File fullPath = new File(dir, name);
93  // TODO: Replace this with a proper FileFilter.
94  return fullPath.isDirectory() && !name.equalsIgnoreCase("cvs") && !name.equalsIgnoreCase(".xvpics") && !name.equalsIgnoreCase(".svn") || name.toLowerCase().endsWith(".art");
95  }
96 
97  };
98 
106  this.archetypeSet = archetypeSet;
107  this.errorView = errorView;
108  this.archetypeParser = archetypeParser;
109  }
110 
115  @NotNull
116  public Collection<G> getInvObjects() {
117  return Collections.unmodifiableCollection(invObjects);
118  }
119 
130  public void loadArchesFromArtifacts(@NotNull final File f, @NotNull final String panelName, @NotNull final String folderName) {
131  final int archetypes = archetypeSet.getArchetypeCount();
132  loadArchesFromArtifactsRecursive(f, "", panelName, folderName);
133  if (LOG.isInfoEnabled()) {
134  LOG.info("Loaded " + (archetypeSet.getArchetypeCount() - archetypes) + " artifacts from '" + f + "'.");
135  }
136  }
137 
149  private void loadArchesFromArtifactsRecursive(@NotNull final File f, @NotNull final String archPath, @NotNull final String panelName, @NotNull final String folderName) {
150  if (f.isDirectory()) {
151  final String[] traverse = f.list(artifactFilenameFilter);
152  if (traverse != null) {
153  Arrays.sort(traverse);
154  for (final String entry : traverse) {
155  loadArchesFromArtifactsRecursive(new File(f, entry), archPath + "/" + entry, panelName, folderName);
156  }
157  }
158  } else {
159  loadArtifact(new ErrorViewCollector(errorView, f), f, archPath, panelName, folderName);
160  }
161  }
162 
173  private void loadArtifact(@NotNull final ErrorViewCollector errorViewCollector, @NotNull final File f, @NotNull final String archPath, @NotNull final String panelName, @NotNull final String folderName) {
174  try {
175  try (FileInputStream fis = new FileInputStream(f)) {
176  try (InputStreamReader isr = new InputStreamReader(fis, IOUtils.MAP_ENCODING)) {
177  try (BufferedReader in = new BufferedReader(isr)) {
178  loadArtifact(in, errorViewCollector, archPath, panelName, folderName);
179  }
180  }
181  }
182  } catch (final IOException ex) {
183  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_FILE_INVALID, ex.getMessage());
184  }
185  }
186 
196  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 {
197  int editorCode = -1;
198  @Nullable String name = null;
199  @Nullable String defArchName = null;
200  int lineCount = 0;
201 
202  @Nullable String editorPath = null;
203  while (true) {
204  final String thisLine2 = in.readLine();
205  if (thisLine2 == null) {
206  break;
207  }
208  lineCount++;
209  final String thisLine = thisLine2.trim();
210  // ignore white space lines or '#' comment lines
211  if (!thisLine.startsWith("#") && !thisLine.isEmpty()) {
212  if (thisLine.startsWith("artifact ")) {
213  name = thisLine.substring(9);
214  } else if (thisLine.startsWith("def_arch ")) {
215  defArchName = thisLine.substring(9);
216  } else if (thisLine.startsWith("editor ")) {
217  final String editor = thisLine.substring(7);
218  final int tIndex = editor.indexOf(':');
219  if (tIndex == -1) {
220  editorCode = Integer.parseInt(editor);
221  } else {
222  editorPath = editor.substring(tIndex + 1);
223  // TODO: use editorPath for determining the place of this GameObject
224  editorCode = Integer.parseInt(editor.substring(0, tIndex));
225  }
226  } else if (thisLine.startsWith("Object")) {
227  if (editorCode == -1) {
228  // TOOD: Warn user
229  }
230  if (editorCode == 0 || editorCode == 2/* || editorCode == -1 */) {
231  // TODO: read until "end"
232  }
233  final String objTitle = thisLine.length() > 7 ? thisLine.substring(7) : "";
234  // TODO: Allow not having a def arch
235  // at this point we MUST have a legal name and def arch
236  if (defArchName == null) {
237  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' has missing def_arch");
238  } else if (defArchName.isEmpty()) {
239  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' has empty def_arch");
240  } else if (name == null) {
241  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' has missing name");
242  } else if (name.isEmpty()) {
243  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' has empty name");
244  } else {
245  try {
246  final R archetype = archetypeSet.getArchetype(defArchName);
247  if (editorCode != 0 && editorCode != 2) { // the next line of our file is part of a arch parse until a "end" comes
248  // now the editor will do the same as the real server:
249  // get the default arch as base and parse the new values over it
250  // the extended functions of the artifacts file can be ignored here.
251  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
252  // note: in the parser is a small part where we handle the title setting
253  // and the reverse type setting for type == -1 (unique items marker in artifacts file)
254  } else {
255  while (true) {
256  final String thisLine3 = in.readLine();
257  if (thisLine3 == null || thisLine3.equals("end")) {
258  break;
259  }
260  }
261  }
262  } catch (final UndefinedArchetypeException ex) {
263  errorViewCollector.addWarning(ErrorViewCategory.ARTIFACT_ENTRY_INVALID, "line " + lineCount + ", Object '" + defArchName + "' / '" + name + "' / '" + objTitle + "' references undefined archetype '" + ex.getMessage() + "'");
264  }
265  }
266  name = null;
267  defArchName = null;
268  editorPath = null;
269  editorCode = -1;
270  }
271  }
272  }
273  }
274 
275 }
net.sf.gridarta.model.archetypeset.ArchetypeSet.getArchetype
R getArchetype(@NotNull String archetypeName)
net.sf.gridarta.model.artifact.ArtifactParser.getInvObjects
Collection< G > getInvObjects()
Definition: ArtifactParser.java:116
net.sf.gridarta
net.sf.gridarta.model.archetype.UndefinedArchetypeException
Definition: UndefinedArchetypeException.java:28
net.sf.gridarta.model.io.AbstractArchetypeParser
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)
Definition: ArtifactParser.java:173
net.sf.gridarta.model.errorview.ErrorView
Definition: ErrorView.java:28
net.sf.gridarta.model.artifact.ArtifactParser
Definition: ArtifactParser.java:52
net.sf.gridarta.model.archetype
Definition: AbstractArchetype.java:20
net.sf.gridarta.model.gameobject.GameObject
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)
Definition: ArtifactParser.java:149
net.sf.gridarta.model.artifact.ArtifactParser.artifactFilenameFilter
final FilenameFilter artifactFilenameFilter
Definition: ArtifactParser.java:88
net.sf.gridarta.model.artifact.ArtifactParser.errorView
final ErrorView errorView
Definition: ArtifactParser.java:70
net.sf.gridarta.model.gameobject
Definition: AbstractGameObject.java:20
net
net.sf.gridarta.model.errorview
Definition: ErrorView.java:20
net.sf.gridarta.model.archetypeset.ArchetypeSet.getArchetypeCount
int getArchetypeCount()
net.sf.gridarta.model.errorview.ErrorViewCollector
Definition: ErrorViewCollector.java:31
net.sf.gridarta.model.errorview.ErrorViewCategory
Definition: ErrorViewCategory.java:28
net.sf.gridarta.model.maparchobject.MapArchObject
Definition: MapArchObject.java:40
net.sf.gridarta.model.artifact.ArtifactParser.archetypeSet
final ArchetypeSet< G, A, R > archetypeSet
Definition: ArtifactParser.java:64
net.sf.gridarta.model.archetypeset.ArchetypeSet
Definition: ArchetypeSet.java:37
net.sf.gridarta.model.io
Definition: AbstractArchetypeParser.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)
Definition: ArtifactParser.java:105
net.sf.gridarta.model
net.sf.gridarta.model.archetype.Archetype
Definition: Archetype.java:41
net.sf.gridarta.model.artifact.ArtifactParser.invObjects
final List< G > invObjects
Definition: ArtifactParser.java:82
net.sf.gridarta.utils.IOUtils
Definition: IOUtils.java:40
net.sf.gridarta.model.artifact.ArtifactParser.archetypeParser
final AbstractArchetypeParser< G, A, R, ?> archetypeParser
Definition: ArtifactParser.java:76
net.sf.gridarta.model.artifact.ArtifactParser.LOG
static final Category LOG
Definition: ArtifactParser.java:58
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)
Definition: ArtifactParser.java:130
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)
Definition: ArtifactParser.java:196
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
Definition: IOUtils.java:52