1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.sequencer.teiid;
25
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Map;
30 import java.util.UUID;
31 import org.modeshape.common.text.Jsr283Encoder;
32 import org.modeshape.common.text.TextEncoder;
33 import org.modeshape.graph.ExecutionContext;
34 import org.modeshape.graph.property.Name;
35 import org.modeshape.graph.property.Path;
36 import org.modeshape.graph.property.PathFactory;
37 import org.modeshape.graph.property.Reference;
38 import org.modeshape.graph.property.ReferenceFactory;
39 import org.modeshape.graph.property.UuidFactory;
40 import org.modeshape.graph.property.ValueFactories;
41 import org.modeshape.graph.property.ValueFactory;
42 import org.modeshape.graph.property.ValueFormatException;
43 import com.google.common.collect.ArrayListMultimap;
44 import com.google.common.collect.Multimap;
45
46
47
48
49 public class ReferenceResolver {
50
51 public static final Map<String, String> STANDARD_DATA_TYPE_URLS_TO_NAMES;
52 public static final Map<UUID, String> STANDARD_DATA_TYPE_URLS_BY_UUID;
53 public static final Map<String, UUID> STANDARD_DATA_TYPE_UUIDS_BY_NAMES;
54 protected static final TextEncoder ENCODER = new Jsr283Encoder();
55 static {
56 Map<String, String> dataTypes = new HashMap<String, String>();
57
58 String sdtUrl = "http://www.metamatrix.com/metamodels/SimpleDatatypes-instance#mmuuid:";
59 dataTypes.put(sdtUrl + "4ca2ae00-3a95-1e20-921b-eeee28353879", "NMTOKEN");
60 dataTypes.put(sdtUrl + "4df43700-3b13-1e20-921b-eeee28353879", "normalizedString");
61 dataTypes.put(sdtUrl + "3425cb80-d844-1e20-9027-be6d2c3b8b3a", "token");
62 dataTypes.put(sdtUrl + "d4d980c0-e623-1e20-8c26-a038c6ed7576", "language");
63 dataTypes.put(sdtUrl + "e66c4600-e65b-1e20-8c26-a038c6ed7576", "Name");
64 dataTypes.put(sdtUrl + "ac00e000-e676-1e20-8c26-a038c6ed7576", "NCName");
65 dataTypes.put(sdtUrl + "4b0f8500-e6a6-1e20-8c26-a038c6ed7576", "NMTOKENS");
66 dataTypes.put(sdtUrl + "dd33ff40-e6df-1e20-8c26-a038c6ed7576", "IDREF");
67 dataTypes.put(sdtUrl + "88b13dc0-e702-1e20-8c26-a038c6ed7576", "ID");
68 dataTypes.put(sdtUrl + "9fece300-e71a-1e20-8c26-a038c6ed7576", "ENTITY");
69 dataTypes.put(sdtUrl + "3c99f780-e72d-1e20-8c26-a038c6ed7576", "IDREFS");
70 dataTypes.put(sdtUrl + "20360100-e742-1e20-8c26-a038c6ed7576", "ENTITIES");
71 dataTypes.put(sdtUrl + "45da3500-e78f-1e20-8c26-a038c6ed7576", "integer");
72 dataTypes.put(sdtUrl + "cbdd6e40-b9d2-1e21-8c26-a038c6ed7576", "nonPositiveInteger");
73 dataTypes.put(sdtUrl + "0e081200-b8a4-1e21-b812-969c8fc8b016", "nonNegativeInteger");
74 dataTypes.put(sdtUrl + "86d29280-b8d3-1e21-b812-969c8fc8b016", "negativeInteger");
75 dataTypes.put(sdtUrl + "8cdee840-b900-1e21-b812-969c8fc8b016", "long");
76 dataTypes.put(sdtUrl + "33add3c0-b98d-1e21-b812-969c8fc8b016", "int");
77 dataTypes.put(sdtUrl + "5bbcf140-b9ae-1e21-b812-969c8fc8b016", "short");
78 dataTypes.put(sdtUrl + "26dc1cc0-b9c8-1e21-b812-969c8fc8b016", "byte");
79 dataTypes.put(sdtUrl + "1cbbd380-b9ea-1e21-b812-969c8fc8b016", "positiveInteger");
80 dataTypes.put(sdtUrl + "54b98780-ba14-1e21-b812-969c8fc8b016", "unsignedLong");
81 dataTypes.put(sdtUrl + "badcbd80-ba63-1e21-b812-969c8fc8b016", "unsignedInt");
82 dataTypes.put(sdtUrl + "327093c0-ba88-1e21-b812-969c8fc8b016", "unsignedShort");
83 dataTypes.put(sdtUrl + "cff745c0-baa2-1e21-b812-969c8fc8b016", "unsignedByte");
84 dataTypes.put(sdtUrl + "bf6c34c0-c442-1e24-9b01-c8207cd53eb7", "string");
85 dataTypes.put(sdtUrl + "dc476100-c483-1e24-9b01-c8207cd53eb7", "boolean");
86 dataTypes.put(sdtUrl + "569dfa00-c456-1e24-9b01-c8207cd53eb7", "decimal");
87 dataTypes.put(sdtUrl + "d86b0d00-c48a-1e24-9b01-c8207cd53eb7", "float");
88 dataTypes.put(sdtUrl + "1f18b140-c4a3-1e24-9b01-c8207cd53eb7", "double");
89 dataTypes.put(sdtUrl + "3b892180-c4a7-1e24-9b01-c8207cd53eb7", "time");
90 dataTypes.put(sdtUrl + "65dcde00-c4ab-1e24-9b01-c8207cd53eb7", "date");
91 dataTypes.put(sdtUrl + "62472700-a064-1e26-9b08-d6079ebe1f0d", "char");
92 dataTypes.put(sdtUrl + "822b9a40-a066-1e26-9b08-d6079ebe1f0d", "biginteger");
93 dataTypes.put(sdtUrl + "f2249740-a078-1e26-9b08-d6079ebe1f0d", "bigdecimal");
94 dataTypes.put(sdtUrl + "6d9809c0-a07e-1e26-9b08-d6079ebe1f0d", "timestamp");
95 dataTypes.put(sdtUrl + "051a0640-b4e8-1e26-9f33-b76fd9d5fa79", "object");
96 dataTypes.put(sdtUrl + "559646c0-4941-1ece-b22b-f49159d22ad3", "clob");
97 dataTypes.put(sdtUrl + "5a793100-1836-1ed0-ba0f-f2334f5fbf95", "blob");
98 dataTypes.put(sdtUrl + "43f5274e-55e1-1f87-ba1c-eea49143eb32", "XMLLiteral");
99 dataTypes.put(sdtUrl + "28d98540-b3e7-1e2a-9a03-beb8638ffd21", "duration");
100 dataTypes.put(sdtUrl + "5c69dec0-b3ea-1e2a-9a03-beb8638ffd21", "dateTime");
101 dataTypes.put(sdtUrl + "17d08040-b3ed-1e2a-9a03-beb8638ffd21", "gYearMonth");
102 dataTypes.put(sdtUrl + "b02c7600-b3f2-1e2a-9a03-beb8638ffd21", "gYear");
103 dataTypes.put(sdtUrl + "6e604140-b3f5-1e2a-9a03-beb8638ffd21", "gMonthDay");
104 dataTypes.put(sdtUrl + "860b7dc0-b3f8-1e2a-9a03-beb8638ffd21", "gDay");
105 dataTypes.put(sdtUrl + "187f5580-b3fb-1e2a-9a03-beb8638ffd21", "gMonth");
106 dataTypes.put(sdtUrl + "6247ec80-e8a4-1e2a-b433-fb67ea35c07e", "anyURI");
107 dataTypes.put(sdtUrl + "eeb5d780-e8c3-1e2a-b433-fb67ea35c07e", "QName");
108 dataTypes.put(sdtUrl + "3dcaf900-e8dc-1e2a-b433-fb67ea35c07e", "NOTATION");
109 dataTypes.put(sdtUrl + "d9998500-ebba-1e2a-9319-8eaa9b2276c7", "hexBinary");
110 dataTypes.put(sdtUrl + "b4c99380-ebc6-1e2a-9319-8eaa9b2276c7", "base64Binary");
111
112
113 Map<UUID, String> dataTypesByUuid = new HashMap<UUID, String>();
114 Map<String, UUID> dataTypeUuidsByName = new HashMap<String, UUID>();
115 for (Map.Entry<String, String> entry : dataTypes.entrySet()) {
116 String url = entry.getKey();
117 String name = entry.getValue();
118 try {
119 UUID uuid = UUID.fromString(url.substring(sdtUrl.length()));
120 dataTypesByUuid.put(uuid, name);
121 dataTypeUuidsByName.put(name, uuid);
122 } catch (Throwable e) {
123 e.printStackTrace();
124 }
125 }
126
127
128 String xsdUrl = "http://www.w3.org/2001/XMLSchema#";
129 for (String value : new HashSet<String>(dataTypes.values())) {
130 dataTypes.put(xsdUrl + value, value);
131 }
132 sdtUrl = "http://www.metamatrix.com/metamodels/SimpleDatatypes-instance#";
133 for (String value : new HashSet<String>(dataTypes.values())) {
134 dataTypes.put(sdtUrl + value, value);
135 }
136
137 STANDARD_DATA_TYPE_URLS_TO_NAMES = Collections.unmodifiableMap(dataTypes);
138 STANDARD_DATA_TYPE_URLS_BY_UUID = Collections.unmodifiableMap(dataTypesByUuid);
139 STANDARD_DATA_TYPE_UUIDS_BY_NAMES = Collections.unmodifiableMap(dataTypeUuidsByName);
140 }
141
142 private final Multimap<Path, UUID> unresolved = ArrayListMultimap.create();
143 private final Map<UUID, Path> mmuuidToNodePath = new HashMap<UUID, Path>();
144 private final Map<UUID, UUID> mmuuidToNodeUuid = new HashMap<UUID, UUID>();
145 private final ValueFactory<String> stringFactory;
146 private final ReferenceFactory referenceFactory;
147 private final PathFactory pathFactory;
148 private final UuidFactory uuidFactory;
149
150 public ReferenceResolver( ExecutionContext context ) {
151 ValueFactories valueFactories = context.getValueFactories();
152 this.referenceFactory = valueFactories.getWeakReferenceFactory();
153 this.uuidFactory = valueFactories.getUuidFactory();
154 this.pathFactory = valueFactories.getPathFactory();
155 this.stringFactory = valueFactories.getStringFactory();
156 }
157
158 public void clear() {
159 mmuuidToNodePath.clear();
160 mmuuidToNodeUuid.clear();
161 unresolved.clear();
162 }
163
164 public void recordXmiUuid( UUID xmiUuid,
165 Path actualPath ) {
166 mmuuidToNodePath.put(xmiUuid, actualPath);
167 }
168
169 public void recordXmiUuidToJcrUuid( UUID xmiUuid,
170 UUID jcrUuid ) {
171 if (xmiUuid != null) mmuuidToNodeUuid.put(xmiUuid, jcrUuid);
172 }
173
174
175
176
177 public Multimap<Path, UUID> getUnresolved() {
178 return unresolved;
179 }
180
181 public UUID resolveInternalReference( String href ) {
182 if (href == null) {
183 return null;
184 }
185 UUID mmuuid = null;
186 if (href.startsWith("mmuuid/")) {
187
188 try {
189 mmuuid = uuidFactory.create(href.substring(7));
190 } catch (ValueFormatException e) {
191
192 }
193 } else {
194 try {
195 mmuuid = uuidFactory.create(href);
196 } catch (ValueFormatException e) {
197
198 }
199 }
200 return mmuuid;
201 }
202
203 public ResolvedReference resolve( Path ownerPath,
204 Name attributeName,
205 String href ) {
206 if (href == null) {
207 return null;
208 }
209
210 String name = STANDARD_DATA_TYPE_URLS_TO_NAMES.get(href);
211 if (name != null) {
212
213 int index = href.indexOf("mmuuid/");
214 String id = null;
215 if (index != -1) {
216 id = href.substring(index + "mmuuid/".length());
217 } else {
218 UUID uuid = STANDARD_DATA_TYPE_UUIDS_BY_NAMES.get(name);
219 if (uuid != null) id = uuid.toString();
220 }
221 return new ResolvedReference(href, name, id);
222 }
223 UUID mmuuid = resolveInternalReference(href);
224 if (mmuuid == null) {
225
226 int index = href.indexOf("mmuuid/");
227 String id = null;
228 if (index != -1) {
229 id = href.substring(index + "mmuuid/".length());
230 }
231 mmuuid = this.uuidFactory.create(id);
232 ResolvedReference result = resolve(ownerPath, attributeName, href, mmuuid);
233 if (result == null) {
234 return new ResolvedReference(href, null, null, id, null);
235 }
236 }
237 return resolve(ownerPath, attributeName, href, mmuuid);
238 }
239
240 public ResolvedReference resolve( Path ownerPath,
241 Name attributeName,
242 String href,
243 UUID mmuuid ) {
244 if (mmuuid == null) {
245 return null;
246 }
247 Path path = mmuuidToNodePath.get(mmuuid);
248 Reference weakReference = referenceFactory.create(mmuuidToNodeUuid.get(mmuuid));
249 if (path == null && ownerPath != null && attributeName != null) {
250
251 Path propPath = pathFactory.create(ownerPath, attributeName);
252 unresolved.put(propPath, mmuuid);
253 }
254 if (path != null || weakReference != null) {
255 String resolvedName = path != null ? stringFactory.create(path.getLastSegment()) : null;
256 return new ResolvedReference(href, resolvedName, path, mmuuid.toString(), weakReference);
257 }
258 return null;
259 }
260
261 public static class ResolvedReference {
262 private final String href;
263 private final Reference reference;
264 private final String name;
265 private final Path path;
266 private final String id;
267 private final boolean standardDataType;
268
269 public ResolvedReference( String href,
270 String standardDataTypeName,
271 String id ) {
272 this.href = href;
273 this.standardDataType = true;
274 this.name = standardDataTypeName;
275 this.id = id;
276 this.reference = null;
277 this.path = null;
278 }
279
280 public ResolvedReference( String href,
281 String name,
282 Path path,
283 String id,
284 Reference reference ) {
285 this.href = href;
286 this.standardDataType = false;
287 this.name = name;
288 this.reference = reference;
289 this.path = path;
290 this.id = id;
291 }
292
293 public boolean isStandardDataType() {
294 return standardDataType;
295 }
296
297 public String getHref() {
298 return href;
299 }
300
301 public String getName() {
302 return name;
303 }
304
305 public Path getPath() {
306 return path;
307 }
308
309 public String getId() {
310 return id;
311 }
312
313 public Reference getWeakReferenceValue() {
314 return reference;
315 }
316 }
317
318 }