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