1 package org.opentrafficsim.editor;
2
3 import java.rmi.RemoteException;
4 import java.util.LinkedHashSet;
5 import java.util.Map.Entry;
6 import java.util.Objects;
7 import java.util.Set;
8
9 import org.djutils.event.Event;
10 import org.djutils.event.EventListener;
11 import org.djutils.event.EventType;
12 import org.djutils.event.reference.ReferenceType;
13 import org.djutils.metadata.MetaData;
14 import org.djutils.metadata.ObjectDescriptor;
15 import org.opentrafficsim.editor.decoration.validation.KeyValidator;
16 import org.opentrafficsim.editor.decoration.validation.KeyrefValidator;
17 import org.opentrafficsim.editor.decoration.validation.XPathValidator;
18 import org.w3c.dom.Node;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 public class XsdTreeNodeRoot extends XsdTreeNode
35 {
36
37
38 private static final long serialVersionUID = 20230224L;
39
40
41 private String schemaLocation;
42
43
44
45
46
47 public static final EventType NODE_CREATED = new EventType("NODECREATED",
48 new MetaData("Node created", "Created tree node",
49 new ObjectDescriptor("Node created", "Created tree node", XsdTreeNode.class),
50 new ObjectDescriptor("Parent", "Parent node", XsdTreeNode.class),
51 new ObjectDescriptor("Index", "Index where it is in the parent", Integer.class)));
52
53
54
55
56
57 public static final EventType NODE_REMOVED = new EventType("NODEREMOVED",
58 new MetaData("Node removed", "Removed tree node",
59 new ObjectDescriptor("Node removed", "Removed tree node", XsdTreeNode.class),
60 new ObjectDescriptor("Parent", "Parent node", XsdTreeNode.class),
61 new ObjectDescriptor("Index", "Index where it was in the parent", Integer.class)));
62
63
64 private String directory;
65
66
67
68
69
70
71 public XsdTreeNodeRoot(final Schema schema) throws RemoteException
72 {
73 super(schema);
74
75 setupXPathListener(schema);
76 }
77
78
79
80
81
82 public String getDirectory()
83 {
84 return this.directory;
85 }
86
87
88
89
90
91 public void setDirectory(final String directory)
92 {
93 if (Objects.equals(this.directory, directory))
94 {
95 return;
96 }
97 this.directory = directory;
98
99 invalidateAll(this);
100 }
101
102 @Override
103 public XsdTreeNodeRoot getRoot()
104 {
105 return this;
106 }
107
108
109
110
111 @Override
112 public boolean addListener(final EventListener listener, final EventType eventType, final int position,
113 final ReferenceType referenceType)
114 {
115 if (NODE_CREATED.equals(eventType))
116 {
117 try
118 {
119 XsdTreeNodeUtil.fireCreatedEventOnExistingNodes(this, listener);
120 }
121 catch (RemoteException exception)
122 {
123 throw new RuntimeException("Unexpected remote exception in local context.", exception);
124 }
125 }
126 return super.addListener(listener, eventType, position, referenceType);
127 }
128
129
130
131
132
133
134
135 private void setupXPathListener(final Schema schema) throws RemoteException
136 {
137
138 Set<KeyValidator> keys = new LinkedHashSet<>();
139 for (Entry<String, Node> entry : schema.keys().entrySet())
140 {
141 String path = entry.getKey().substring(0, entry.getKey().lastIndexOf("."));
142 keys.add(new KeyValidator(entry.getValue(), path));
143 }
144 Set<KeyValidator> uniques = new LinkedHashSet<>();
145 for (Entry<String, Node> entry : schema.uniques().entrySet())
146 {
147 String path = entry.getKey().substring(0, entry.getKey().lastIndexOf("."));
148 uniques.add(new KeyValidator(entry.getValue(), path));
149 }
150 Set<KeyrefValidator> keyrefs = new LinkedHashSet<>();
151 for (Entry<String, Node> entry : schema.keyrefs().entrySet())
152 {
153 String keyName = DocumentReader.getAttribute(entry.getValue(), "refer").replace("ots:", "");
154 for (KeyValidator key : keys)
155 {
156 if (key.getKeyName().equals(keyName))
157 {
158 String path = entry.getKey().substring(0, entry.getKey().lastIndexOf("."));
159 keyrefs.add(new KeyrefValidator(entry.getValue(), path, key));
160 break;
161 }
162 }
163 for (KeyValidator unique : uniques)
164 {
165 if (unique.getKeyName().equals(keyName))
166 {
167 String path = entry.getKey().substring(0, entry.getKey().lastIndexOf("."));
168 keyrefs.add(new KeyrefValidator(entry.getValue(), path, unique));
169 break;
170 }
171 }
172 }
173
174 EventListener listener = new EventListener()
175 {
176
177 private static final long serialVersionUID = 20230228L;
178
179 @Override
180 public void notify(final Event event) throws RemoteException
181 {
182 int iteration = 0;
183 Set<? extends XPathValidator> keysIteration = keys;
184 XsdTreeNode node = (XsdTreeNode) ((Object[]) event.getContent())[0];
185 while (iteration < 3)
186 {
187 for (XPathValidator key : keysIteration)
188 {
189 if (event.getType().equals(NODE_CREATED))
190 {
191 key.addNode(node);
192 }
193 else
194 {
195 key.removeNode(node);
196 }
197 }
198 keysIteration = iteration == 0 ? keyrefs : uniques;
199 iteration++;
200 }
201 }
202 };
203
204 addListener(listener, NODE_CREATED);
205 addListener(listener, NODE_REMOVED);
206 }
207
208
209
210
211
212 public void setSchemaLocation(final String schemaLocation)
213 {
214 this.schemaLocation = schemaLocation;
215 }
216
217
218
219
220
221 public String getSchemaLocation()
222 {
223 return this.schemaLocation;
224 }
225
226 }