1 |
1e2b2c27
|
Tomáš Šimandl
|
/**
|
2 |
|
|
* @constructor
|
3 |
|
|
*/
|
4 |
|
|
function JavaComponentChanger() {
|
5 |
|
|
var javaClasses = {
|
6 |
|
|
boolean: 'java.lang.Boolean',
|
7 |
|
|
string: 'java.lang.String',
|
8 |
|
|
list: 'java.util.List',
|
9 |
|
|
set: 'java.util.Set',
|
10 |
|
|
};
|
11 |
|
|
|
12 |
|
|
var crceClasses = {
|
13 |
|
|
package: 'crce.api.java.package',
|
14 |
|
|
class: 'crce.api.java.class',
|
15 |
|
|
method: 'crce.api.java.method',
|
16 |
|
|
property: 'crce.api.java.property',
|
17 |
|
|
};
|
18 |
|
|
|
19 |
|
|
var ns = ''; // http://relisa.kiv.zcu.cz
|
20 |
|
|
var xsi = 'http://www.w3.org/2001/XMLSchema-instance';
|
21 |
|
|
var xsd = 'crce.xsd';
|
22 |
|
|
|
23 |
|
|
var xmlDocument;
|
24 |
|
|
var nodeCounter;
|
25 |
|
|
|
26 |
|
|
var xmlParser = new DOMParser();
|
27 |
|
|
var xmlSerializer = new XMLSerializer();
|
28 |
|
|
|
29 |
|
|
/**
|
30 |
|
|
* Sends change requirements to CRCE.
|
31 |
|
|
* @param {array} components Components to be changed.
|
32 |
|
|
* @param {boolean} includeNotFound True if not found classes should be added as change requirements, otherwise false.
|
33 |
|
|
*/
|
34 |
|
|
this.run = function(components, includeNotFound) {
|
35 |
|
|
if (components.length === 0) return;
|
36 |
|
|
|
37 |
|
|
// initialize requirements XML to be sent to CRCE
|
38 |
|
|
xmlDocument = constructXmlDocument(components, includeNotFound);
|
39 |
|
|
|
40 |
|
|
console.log('CRCE request:', xmlDocument);
|
41 |
|
|
|
42 |
|
|
// trigger change
|
43 |
|
|
return $.ajax({
|
44 |
|
|
type: 'POST', // jQuery docs tells to use "method" but it doesn't work and always sends GET -> use "type" instead
|
45 |
|
|
url: app.constants.crceApiBase + '/metadata/catalogue/',
|
46 |
|
|
data: xmlSerializer.serializeToString(xmlDocument),
|
47 |
|
|
contentType: 'application/xml',
|
48 |
|
|
timeout: 180 * 1000, // in milliseconds
|
49 |
|
|
|
50 |
|
|
}).then(function(data, textStatus, jqXHR) {
|
51 |
|
|
console.log('CRCE response:', data);
|
52 |
|
|
|
53 |
|
|
var resourcesEl = data.childNodes[0];
|
54 |
|
|
if (resourcesEl.childNodes.length === 0) {
|
55 |
|
|
return $.Deferred().reject('CRCE did not find any resources fitting your requirements.').promise();
|
56 |
|
|
}
|
57 |
|
|
|
58 |
|
|
var proposals = [];
|
59 |
|
|
|
60 |
|
|
resourcesEl.childNodes.forEach(function(resourceEl, index) {
|
61 |
|
|
var proposal = {
|
62 |
|
|
uuid: resourceEl.getAttribute('uuid'),
|
63 |
|
|
};
|
64 |
|
|
|
65 |
|
|
var capabilityEl = resourceEl.childNodes[0];
|
66 |
|
|
capabilityEl.childNodes.forEach(function(attributeEl) {
|
67 |
|
|
if (['name', 'external-id', 'version'].includes(attributeEl.getAttribute('name'))) {
|
68 |
|
|
proposal[attributeEl.getAttribute('name')] = attributeEl.getAttribute('value');
|
69 |
|
|
}
|
70 |
|
|
});
|
71 |
|
|
proposals.push(proposal);
|
72 |
|
|
});
|
73 |
|
|
|
74 |
|
|
return proposals;
|
75 |
|
|
});
|
76 |
|
|
};
|
77 |
|
|
|
78 |
|
|
function constructXmlDocument(components, includeNotFound) {
|
79 |
|
|
// initialize requirements XML to be sent to CRCE
|
80 |
|
|
xmlDocument = document.implementation.createDocument(ns, 'requirements', null);
|
81 |
|
|
//xmlDocument.documentElement.setAttributeNS(xsi, 'xsi:schemaLocation', ns + ' ' + xsd);
|
82 |
|
|
|
83 |
|
|
nodeCounter = 0;
|
84 |
|
|
|
85 |
|
|
// optimize returned results
|
86 |
|
|
var optimizeByRequirementEl = xmlDocument.createElementNS(ns, 'requirement');
|
87 |
|
|
optimizeByRequirementEl.setAttribute('namespace', 'result.optimize-by');
|
88 |
|
|
|
89 |
|
|
var optimizeByFunctionAttributeEl = xmlDocument.createElementNS(ns, 'attribute');
|
90 |
|
|
optimizeByFunctionAttributeEl.setAttribute('name', 'function-ID');
|
91 |
|
|
optimizeByFunctionAttributeEl.setAttribute('type', javaClasses.string);
|
92 |
|
|
optimizeByFunctionAttributeEl.setAttribute('value', 'cf-equal-cost');
|
93 |
|
|
|
94 |
|
|
var optimizeByMethodAttributeEl = xmlDocument.createElementNS(ns, 'attribute');
|
95 |
|
|
optimizeByMethodAttributeEl.setAttribute('name', 'method-ID');
|
96 |
|
|
optimizeByMethodAttributeEl.setAttribute('type', javaClasses.string);
|
97 |
|
|
optimizeByMethodAttributeEl.setAttribute('value', 'ro-ilp-direct-dependencies');
|
98 |
|
|
|
99 |
|
|
optimizeByRequirementEl.appendChild(optimizeByFunctionAttributeEl);
|
100 |
|
|
optimizeByRequirementEl.appendChild(optimizeByMethodAttributeEl);
|
101 |
|
|
|
102 |
|
|
xmlDocument.documentElement.appendChild(optimizeByRequirementEl);
|
103 |
|
|
|
104 |
|
|
// component does not have to fulfill all requirements
|
105 |
|
|
var directiveEl = xmlDocument.createElementNS(ns, 'directive');
|
106 |
|
|
directiveEl.setAttribute('name', 'operator');
|
107 |
|
|
directiveEl.setAttribute('value', 'or');
|
108 |
|
|
|
109 |
|
|
xmlDocument.documentElement.appendChild(directiveEl);
|
110 |
|
|
|
111 |
|
|
// component requirements
|
112 |
|
|
components.forEach(function(component) {
|
113 |
|
|
var inEdgeList = component.getInEdgeList();
|
114 |
|
|
if (!includeNotFound) {
|
115 |
|
|
inEdgeList = inEdgeList.filter(function(edge) {
|
116 |
|
|
return edge.getFrom().name !== app.constants.notFoundVertexName;
|
117 |
|
|
});
|
118 |
|
|
}
|
119 |
|
|
|
120 |
|
|
if (inEdgeList.length === 0) return;
|
121 |
|
|
|
122 |
|
|
// construct functionality requirements tree
|
123 |
|
|
inEdgeList.forEach(function(edge) {
|
124 |
|
|
var compatibilityInfoList = edge.getCompatibilityInfo();
|
125 |
|
|
|
126 |
|
|
compatibilityInfoList.forEach(function(compatibilityInfo) {
|
127 |
|
|
compatibilityInfo.incomps.forEach(function(incompatibility) {
|
128 |
|
|
appendRequirementTree(xmlDocument.documentElement, incompatibility);
|
129 |
|
|
});
|
130 |
|
|
});
|
131 |
|
|
});
|
132 |
|
|
});
|
133 |
|
|
|
134 |
|
|
return xmlDocument;
|
135 |
|
|
}
|
136 |
|
|
|
137 |
|
|
function appendRequirementTree(element, incompatibility) {
|
138 |
|
|
var type = incompatibility.desc.type;
|
139 |
|
|
|
140 |
|
|
if (app.utils.isUndefined(type)) {
|
141 |
|
|
incompatibility.subtree.forEach(function(incompatibility) {
|
142 |
|
|
appendRequirementTree(element, incompatibility);
|
143 |
|
|
});
|
144 |
|
|
|
145 |
|
|
} else {
|
146 |
|
|
// add package for classes
|
147 |
|
|
if (type === 'class') {
|
148 |
|
|
var packageRequirementEl = xmlDocument.createElementNS(ns, 'requirement');
|
149 |
|
|
packageRequirementEl.setAttribute('uuid', nodeCounter++);
|
150 |
|
|
packageRequirementEl.setAttribute('namespace', crceClasses['package']);
|
151 |
|
|
|
152 |
|
|
var packageAttributeEl = xmlDocument.createElementNS(ns, 'attribute');
|
153 |
|
|
packageAttributeEl.setAttribute('name', 'name');
|
154 |
|
|
packageAttributeEl.setAttribute('type', javaClasses.string);
|
155 |
|
|
packageAttributeEl.setAttribute('value', incompatibility.desc.details.package);
|
156 |
|
|
|
157 |
|
|
packageRequirementEl.appendChild(packageAttributeEl);
|
158 |
|
|
}
|
159 |
|
|
|
160 |
|
|
var requirementEl = xmlDocument.createElementNS(ns, 'requirement');
|
161 |
|
|
requirementEl.setAttribute('uuid', nodeCounter++);
|
162 |
|
|
requirementEl.setAttribute('namespace', crceClasses[type]);
|
163 |
|
|
|
164 |
|
|
// attributes
|
165 |
|
|
var details = incompatibility.desc.details;
|
166 |
|
|
for (var key in details) {
|
167 |
|
|
if (!details.hasOwnProperty(key)) continue;
|
168 |
|
|
if (key === 'package') continue;
|
169 |
|
|
|
170 |
|
|
var value = details[key];
|
171 |
|
|
|
172 |
|
|
// TODO: fix for JaCC not returning correct values for abstract classes and interfaces
|
173 |
|
|
if (key === 'abstract' || key === 'interface') continue;
|
174 |
|
|
|
175 |
|
|
var attributeType;
|
176 |
|
|
switch (typeof value) {
|
177 |
|
|
case 'boolean':
|
178 |
|
|
attributeType = javaClasses.boolean;
|
179 |
|
|
break;
|
180 |
|
|
case 'object':
|
181 |
|
|
if (value.constructor.name === 'Array') {
|
182 |
|
|
attributeType = javaClasses.list;
|
183 |
|
|
break;
|
184 |
|
|
}
|
185 |
|
|
default:
|
186 |
|
|
attributeType = javaClasses.string;
|
187 |
|
|
}
|
188 |
|
|
|
189 |
|
|
var attributeEl = xmlDocument.createElementNS(ns, 'attribute');
|
190 |
|
|
attributeEl.setAttribute('name', key);
|
191 |
|
|
attributeEl.setAttribute('type', attributeType);
|
192 |
|
|
attributeEl.setAttribute('value', value);
|
193 |
|
|
|
194 |
|
|
requirementEl.appendChild(attributeEl);
|
195 |
|
|
}
|
196 |
|
|
|
197 |
|
|
// children
|
198 |
|
|
incompatibility.subtree.forEach(function(incompatibility) {
|
199 |
|
|
appendRequirementTree(requirementEl, incompatibility);
|
200 |
|
|
});
|
201 |
|
|
|
202 |
|
|
// add package for classes
|
203 |
|
|
if (type === 'class') {
|
204 |
|
|
packageRequirementEl.appendChild(requirementEl);
|
205 |
|
|
element.appendChild(packageRequirementEl);
|
206 |
|
|
} else {
|
207 |
|
|
element.appendChild(requirementEl);
|
208 |
|
|
}
|
209 |
|
|
}
|
210 |
|
|
}
|
211 |
|
|
}
|