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
103 @Override
104 public XsdTreeNodeRoot getRoot()
105 {
106 return this;
107 }
108
109
110
111
112 @Override
113 public boolean addListener(final EventListener listener, final EventType eventType, final int position,
114 final ReferenceType referenceType)
115 {
116 if (NODE_CREATED.equals(eventType))
117 {
118 try
119 {
120 XsdTreeNodeUtil.fireCreatedEventOnExistingNodes(this, listener);
121 }
122 catch (RemoteException exception)
123 {
124 throw new RuntimeException("Unexpected remote exception in local context.", exception);
125 }
126 }
127 return super.addListener(listener, eventType, position, referenceType);
128 }
129
130
131
132
133
134
135
136 private void setupXPathListener(final Schema schema) throws RemoteException
137 {
138
139 Set<KeyValidator> keys = new LinkedHashSet<>();
140 for (Entry<String, Node> entry : schema.keys().entrySet())
141 {
142 String path = entry.getKey().substring(0, entry.getKey().lastIndexOf("."));
143 keys.add(new KeyValidator(entry.getValue(), path));
144 }
145 Set<KeyValidator> uniques = new LinkedHashSet<>();
146 for (Entry<String, Node> entry : schema.uniques().entrySet())
147 {
148 String path = entry.getKey().substring(0, entry.getKey().lastIndexOf("."));
149 uniques.add(new KeyValidator(entry.getValue(), path));
150 }
151 Set<KeyrefValidator> keyrefs = new LinkedHashSet<>();
152 for (Entry<String, Node> entry : schema.keyrefs().entrySet())
153 {
154 String keyName = DocumentReader.getAttribute(entry.getValue(), "refer").replace("ots:", "");
155 for (KeyValidator key : keys)
156 {
157 if (key.getKeyName().equals(keyName))
158 {
159 String path = entry.getKey().substring(0, entry.getKey().lastIndexOf("."));
160 keyrefs.add(new KeyrefValidator(entry.getValue(), path, key));
161 break;
162 }
163 }
164 for (KeyValidator unique : uniques)
165 {
166 if (unique.getKeyName().equals(keyName))
167 {
168 String path = entry.getKey().substring(0, entry.getKey().lastIndexOf("."));
169 keyrefs.add(new KeyrefValidator(entry.getValue(), path, unique));
170 break;
171 }
172 }
173 }
174
175
176 EventListener listener = new EventListener()
177 {
178
179 private static final long serialVersionUID = 20230228L;
180
181
182 @Override
183 public void notify(final Event event) throws RemoteException
184 {
185 int iteration = 0;
186 Set<? extends XPathValidator> keysIteration = keys;
187 XsdTreeNode node = (XsdTreeNode) ((Object[]) event.getContent())[0];
188 while (iteration < 3)
189 {
190 for (XPathValidator key : keysIteration)
191 {
192 if (event.getType().equals(NODE_CREATED))
193 {
194 key.addNode(node);
195 }
196 else
197 {
198 key.removeNode(node);
199 }
200 }
201 keysIteration = iteration == 0 ? keyrefs : uniques;
202 iteration++;
203 }
204 }
205 };
206
207 addListener(listener, NODE_CREATED);
208 addListener(listener, NODE_REMOVED);
209 }
210
211
212
213
214
215 public void setSchemaLocation(final String schemaLocation)
216 {
217 this.schemaLocation = schemaLocation;
218 }
219
220
221
222
223
224 public String getSchemaLocation()
225 {
226 return this.schemaLocation;
227 }
228
229 }