Gridarta Editor
NamedTreeNode.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.data;
21 
22 import java.io.Serializable;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.Enumeration;
28 import java.util.SortedMap;
29 import java.util.TreeMap;
30 import javax.swing.tree.TreeNode;
31 import javax.swing.tree.TreePath;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.annotations.Nullable;
34 
40 public class NamedTreeNode<E extends NamedObject> implements TreeNode, Comparable<NamedTreeNode<E>>, Serializable {
41 
45  private static final long serialVersionUID = 1L;
46 
51  @NotNull
52  private final SortedMap<String, NamedTreeNode<E>> childNodes = new TreeMap<>();
53 
60  private NamedTreeNode<?> @Nullable [] childNodeArray;
61 
66  @Nullable
67  private final NamedTreeNode<E> parent;
68 
73  @NotNull
74  private final String name;
75 
80  @Nullable
81  private final NamedObject namedObject;
82 
88  private final boolean dir;
89 
94  public NamedTreeNode() {
95  this(true, null, "/");
96  }
97 
107  private NamedTreeNode(final boolean dir, @Nullable final NamedTreeNode<E> parent, @NotNull final String name) {
108  this.dir = dir;
109  this.parent = parent;
110  this.name = name;
111  namedObject = null;
112  }
113 
122  private NamedTreeNode(final boolean dir, @Nullable final NamedTreeNode<E> parent, @NotNull final NamedObject namedObject) {
123  this.dir = dir;
124  this.parent = parent;
126  this.namedObject = namedObject;
127  }
128 
134  public void append(@NotNull final NamedObject namedObject) throws IllegalNamedObjectException {
135  if (parent != null) {
136  throw new IllegalNamedObjectException("node '" + namedObject.getPath() + "' is not a root node");
137  }
139  }
140 
147  private void append(@NotNull final String path, @NotNull final NamedObject namedObject) throws IllegalNamedObjectException {
148  childNodeArray = null;
149  if (!dir) {
150  throw new IllegalNamedObjectException("cannot insert '" + path + "' into non-directory node for '" + namedObject.getPath() + "'");
151  }
152  String realName = path.startsWith("/") ? path.substring(1) : path;
153  // Now we have the child node name in realName
154  if (realName.contains("/")) {
155  // Find directory node and append there
156  final String dirName = realName.substring(0, realName.indexOf('/'));
157  realName = realName.substring(realName.indexOf('/'));
158  NamedTreeNode<E> dirNode = childNodes.get(dirName);
159  if (dirNode == null) {
160  dirNode = new NamedTreeNode<>(true, this, dirName);
161  childNodes.put(dirName, dirNode);
162  }
163  dirNode.append(realName, namedObject);
164  } else {
165  // Append face node to this
166  //realName = realName.substring(0, realName.length() - 4);
167  final NamedTreeNode<E> faceNode = new NamedTreeNode<>(false, this, namedObject);
168  childNodes.put(realName, faceNode);
169  }
170  }
171 
175  private void initLazyArray() {
176  if (childNodeArray == null) {
177  childNodeArray = childNodes.values().toArray(new NamedTreeNode<?>[0]);
178  }
179  }
180 
181  // --Commented out by Inspection START (09.06.05 04:00):
182  // /** Check whether this is a directory node.
183  // * @return {@code true} for directory nodes, {@code false} for face nodes
184  // */
185  // public final boolean isDir() {
186  // return dir;
187  // }
188  // --Commented out by Inspection STOP (09.06.05 04:00)
189 
196  @Nullable
197  public NamedObject getNamedObject() {
198  return namedObject;
199  }
200 
205  @NotNull
206  public String getName() {
207  return name;
208  }
209 
210  @NotNull
211  @Override
212  public Enumeration<NamedTreeNode<E>> children() {
213  return Collections.enumeration(childNodes.values());
214  }
215 
219  @Override
220  public boolean getAllowsChildren() {
221  return dir;
222  }
223 
224  @NotNull
225  @Override
226  public TreeNode getChildAt(final int childIndex) {
227  initLazyArray();
228  assert childNodeArray != null;
229  return childNodeArray[childIndex];
230  }
231 
232  @Override
233  public int getChildCount() {
234  return childNodes.size();
235  }
236 
237  @Override
238  public int getIndex(@NotNull final TreeNode node) {
239  initLazyArray();
240  final int result = Arrays.binarySearch(childNodeArray, node);
241  return result < 0 ? -1 : result;
242  }
243 
244  @Nullable
245  @Override
246  public NamedTreeNode<E> getParent() {
247  return parent;
248  }
249 
253  @Override
254  public boolean isLeaf() {
255  return !dir;
256  }
257 
258  @Override
259  public boolean equals(@Nullable final Object obj) {
260  if (obj == this) {
261  return true;
262  }
263  if (obj == null || obj.getClass() != getClass()) {
264  return false;
265  }
266  final NamedTreeNode<?> namedTreeNode = (NamedTreeNode<?>) obj;
267  return dir == namedTreeNode.dir && name.equals(namedTreeNode.name);
268  }
269 
270  @Override
271  public int hashCode() {
272  return (dir ? 1 : 0) ^ name.hashCode();
273  }
274 
275  @Override
276  public int compareTo(@NotNull final NamedTreeNode<E> o) {
277  return dir ^ !o.dir ? name.compareTo(o.name) : dir ? -1 : 1;
278  }
279 
285  @NotNull
286  public TreePath getPathFor(@NotNull final String path) {
287  final Collection<NamedTreeNode<E>> nodes = new ArrayList<>();
288  String currentPath = path;
289  // XXX This is ugly but it works, no time to think about it now.
290  String dirPart;
291  for (NamedTreeNode<E> currentNode = this; currentNode != null; currentNode = currentNode.childNodes.get(dirPart)) {
292  nodes.add(currentNode);
293  if (currentPath.indexOf('/', 1) >= 0) {
294  dirPart = currentPath.substring(1, currentPath.indexOf('/', 1));
295  currentPath = currentPath.substring(currentPath.indexOf('/', 1));
296  } else if (currentPath.indexOf('/') >= 0) {
297  dirPart = currentPath.substring(1);
298  currentPath = "";
299  } else {
300  break;
301  }
302  }
303  return new TreePath(nodes.toArray());
304  }
305 
306  @NotNull
307  @Override
308  public String toString() {
309  return name;
310  }
311 
312 }
net.sf.gridarta.model.data.NamedTreeNode.childNodeArray
NamedTreeNode<?>[] childNodeArray
The node array.
Definition: NamedTreeNode.java:60
net.sf.gridarta.model.data.IllegalNamedObjectException
Exception thrown to indicate that a named object is not acceptable.
Definition: IllegalNamedObjectException.java:28
net.sf.gridarta.model.data.NamedTreeNode.NamedTreeNode
NamedTreeNode(final boolean dir, @Nullable final NamedTreeNode< E > parent, @NotNull final String name)
Creates a new instance.
Definition: NamedTreeNode.java:107
net.sf.gridarta.model.data.NamedTreeNode.serialVersionUID
static final long serialVersionUID
The serial version UID.
Definition: NamedTreeNode.java:45
net.sf.gridarta.model.data.NamedTreeNode.append
void append(@NotNull final String path, @NotNull final NamedObject namedObject)
Appends a node.
Definition: NamedTreeNode.java:147
net.sf.gridarta.model.data.NamedObject
An.
Definition: NamedObject.java:32
net.sf.gridarta.model.data.NamedTreeNode
TreeNode implementation for Named Objects (like arches, faces, animations, artifacts etc....
Definition: NamedTreeNode.java:40
net.sf.gridarta.model.data.NamedObject.getName
String getName()
Get the name of this AbstractNamedObject.
net.sf.gridarta.model.data.NamedTreeNode.dir
final boolean dir
Directory state,.
Definition: NamedTreeNode.java:88
net.sf.gridarta.model.data.NamedTreeNode.append
void append(@NotNull final NamedObject namedObject)
Append a node.
Definition: NamedTreeNode.java:134
net.sf.gridarta.model.data.NamedTreeNode.NamedTreeNode
NamedTreeNode()
Creates a root node.
Definition: NamedTreeNode.java:94
net.sf.gridarta.model.data.NamedTreeNode.name
final String name
The node name.
Definition: NamedTreeNode.java:74
net.sf.gridarta.model.data.NamedTreeNode.initLazyArray
void initLazyArray()
Makes sure that the variable childNodeArray points to a valid array.
Definition: NamedTreeNode.java:175
net.sf.gridarta.model.data.NamedTreeNode.namedObject
final NamedObject namedObject
The node object.
Definition: NamedTreeNode.java:81
net.sf.gridarta.model.data.NamedObject.getPath
String getPath()
Get the path of this AbstractNamedObject.
net.sf.gridarta.model.data.NamedTreeNode.NamedTreeNode
NamedTreeNode(final boolean dir, @Nullable final NamedTreeNode< E > parent, @NotNull final NamedObject namedObject)
Creates a new instance.
Definition: NamedTreeNode.java:122
net.sf.gridarta.model.data.NamedTreeNode.childNodes
final SortedMap< String, NamedTreeNode< E > > childNodes
The children.
Definition: NamedTreeNode.java:52
net.sf.gridarta.model.data.NamedTreeNode.parent
final NamedTreeNode< E > parent
The parent node, which may be.
Definition: NamedTreeNode.java:67