/
ESONLinkingService.java
156 lines (140 loc) · 6.08 KB
/
ESONLinkingService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
* #%L
* org.eclipse.emf.eson
* %%
* Copyright (C) 2016 Michael Vorburger and others
* %%
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* #L%
*/package org.eclipse.emf.eson.scoping;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.eson.eFactory.EFactoryPackage;
import org.eclipse.emf.eson.eFactory.PackageImport;
import org.eclipse.emf.eson.util.EPackageRegistry;
import org.eclipse.xtext.linking.impl.DefaultLinkingService;
import org.eclipse.xtext.linking.impl.IllegalNodeException;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.IResourceDescriptions;
import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider;
import org.eclipse.xtext.scoping.IGlobalScopeProvider;
import org.eclipse.xtext.scoping.IScope;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.inject.Inject;
/**
* ILinkingService which deals with EPackage references in a particular manner.
*
* @see org.eclipse.xtext.xtext.XtextLinkingService which was the inspiration for this class
*
* @author Michael Vorburger
*/
@SuppressWarnings("restriction")
public class ESONLinkingService extends DefaultLinkingService {
private static final Logger log = Logger.getLogger(ESONLinkingService.class);
private @Inject IGlobalScopeProvider scopeProvider;
private @Inject ResourceDescriptionsProvider descriptionsProvider;
private @Inject EPackageRegistry ePackageRegistry;
@Override
public List<EObject> getLinkedObjects(EObject context, EReference ref, INode node) throws IllegalNodeException {
if (ref == EFactoryPackage.eINSTANCE.getPackageImport_EPackage() && context instanceof PackageImport)
return getPackage((PackageImport)context, getLinkingHelper().getCrossRefNodeAsString(node, true));
return super.getLinkedObjects(context, ref, node);
}
// Following code is (way too much..) copy/pasted (almost) verbatim/as-is from XtextLinkingService
// Proposed to Xtext to factor out re-usable code not related to xtext.xtext,
// but of interest to any langs dealing with EPackage, via bug/issue
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=489748.
private List<EObject> getPackage(PackageImport context, String nsUri) {
if (nsUri == null)
return Collections.emptyList();
QualifiedName packageNsURI = QualifiedName.create(nsUri);
EPackage pack = findPackageInScope(context, packageNsURI);
if (pack == null) {
pack = findPackageInAllDescriptions(context, packageNsURI);
if (pack == null) {
pack = loadEPackage(nsUri, context.eResource().getResourceSet());
}
}
if (pack != null)
return Collections.<EObject>singletonList(pack);
return Collections.emptyList();
}
private EPackage findPackageInScope(EObject context, QualifiedName packageNsURI) {
IScope scopedPackages = scopeProvider.getScope(context.eResource(), EFactoryPackage.Literals.PACKAGE_IMPORT__EPACKAGE, new Predicate<IEObjectDescription>() {
@Override
public boolean apply(IEObjectDescription input) {
return isNsUriIndexEntry(input);
}
});
IEObjectDescription description = scopedPackages.getSingleElement(packageNsURI);
if (description != null) {
return getResolvedEPackage(description, context);
}
return null;
}
private EPackage findPackageInAllDescriptions(EObject context, QualifiedName packageNsURI) {
IResourceDescriptions descriptions = descriptionsProvider.getResourceDescriptions(context.eResource());
if (descriptions != null) {
Iterable<IEObjectDescription> exported = descriptions.getExportedObjects(EcorePackage.Literals.EPACKAGE, packageNsURI, false);
for(IEObjectDescription candidate: exported) {
if (isNsUriIndexEntry(candidate)) {
EPackage result = getResolvedEPackage(candidate, context);
if (result != null)
return result;
}
}
}
return null;
}
private EPackage loadEPackage(String resourceOrNsURI, ResourceSet resourceSet) {
Optional<EPackage> optionalResult = ePackageRegistry.getEPackage(resourceSet, resourceOrNsURI);
if (optionalResult.isPresent())
return optionalResult.get();
URI uri = URI.createURI(resourceOrNsURI);
try {
if ("http".equalsIgnoreCase(uri.scheme()))
return null;
if (uri.fragment() == null) {
Resource resource = resourceSet.getResource(uri, true);
if (resource.getContents().isEmpty())
return null;
EPackage result = (EPackage) resource.getContents().get(0);
return result;
}
EPackage result = (EPackage) resourceSet.getEObject(uri, true);
return result;
} catch(RuntimeException ex) {
if (uri.isPlatformResource()) {
String platformString = uri.toPlatformString(true);
URI platformPluginURI = URI.createPlatformPluginURI(platformString, true);
return loadEPackage(platformPluginURI.toString(), resourceSet);
}
log.trace("Cannot load package with URI '" + resourceOrNsURI + "'", ex);
return null;
}
}
private EPackage getResolvedEPackage(IEObjectDescription description, EObject context) {
EObject resolved = EcoreUtil.resolve(description.getEObjectOrProxy(), context);
if (resolved != null && !resolved.eIsProxy() && resolved instanceof EPackage)
return (EPackage) resolved;
return null;
}
private boolean isNsUriIndexEntry(IEObjectDescription candidate) {
return Boolean.TRUE.toString().equalsIgnoreCase(candidate.getUserData("nsURI"));
}
}