Projekt

Obecné

Profil

Stáhnout (6.79 KB) Statistiky
| Větev: | Tag: | Revize:
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
}