blob: bebc98067ecda3bb5f730e0db472e616c3b68a42 [file] [log] [blame]
// Copyright (c) 2000-2019 Ericsson Telecom AB Telecom AB //
// All rights reserved. This program and the accompanying materials are made available under the //
// terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at //
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html //
///////////////////////////////////////////////////////////////////////////////////////////////////////
function GuiEditor_SanityChecker_ViewModel(p_model, p_parent) {
"use strict";
var v_model = p_model;
var v_fileHandler = v_model.getFileHandler();
var v_parent = p_parent;
var v_help;
var v_request;
var v_cache;
var v_this = this;
///////////////////// GENERAL VIEWMODEL FUNCTIONS /////////////////////
this.init = function(p_callback) {
v_cache = {};
function jsImported(ok, data) {
if (!ok) {
alert("Some javascript files could not be imported\n" + JSON.stringify(data, null, 4));
}
p_callback(true);
}
new MultipleDirectoryListTask([
v_model.getAppConfig().lastEditedApp + "/ViewModels",
"WebApplications/CustomizableApp/ViewModels",
v_model.getAppConfig().lastEditedApp + "/Views",
"WebApplications/CustomizableApp/Views"
], v_fileHandler).taskOperation(function(ok, resources) {
new JsImportTaskList(resources.jsfiles, v_fileHandler, jsImported).taskOperation();
});
};
this.setHelp = function(p_help) {
v_help = p_help;
};
this.setSetup = function(p_setup) {
v_request = p_setup.request.getData();
};
this.addFile = function(fileName) {
v_fileHandler.importJsFile(fileName, function(ok, msg) {
if (!ok) {
alert("Javascript file invalid, import failed: " + fileName + "\n" + msg);
}
});
};
///////////////////// INTERFACE FOR VALIDATION AND GETTING HELP /////////////////////
this.isValidView = function(view, connectedViewmodels) {
var viewClass = view.getClass();
if (window[viewClass] != undefined) {
// check expected interfaces
if (window[viewClass].expectsInterface != undefined) {
var expectedInterfaces = window[viewClass].expectsInterface();
for (var i = 0; i < connectedViewmodels.length; ++i) {
var viewmodelClass = connectedViewmodels[i].getClass();
if (window[viewmodelClass] != undefined && window[viewmodelClass].providesInterface != undefined) {
var providedInterface = window[viewmodelClass].providesInterface();
var useful = false;
for (var j = 0; j < expectedInterfaces.length; ++j) {
var listToSearch = findMandatoryOrOptional(expectedInterfaces[j]);;
if (listToSearch != undefined && isSubsetOf(listToSearch, providedInterface)) {
expectedInterfaces[j].fulfilled = true;
useful = true;
}
}
if (!useful) {
return "connected viewmodel " + i + " of class " + viewmodelClass + " does not provide an expected interface";
}
}
}
for (var i = 0; i < expectedInterfaces.length; ++i) {
if (!expectedInterfaces[i].fulfilled && expectedInterfaces[i].mandatory != undefined) {
return "an interface is not fulfilled: " + expectedInterfaces[i].mandatory;
}
}
}
// chack if custom data is valid
if (window[viewClass].getCustomDataSchema != undefined && !oldff) {
var validate = new Ajv({}).compile(window[viewClass].getCustomDataSchema());
var isValid = validate(view.getCustomData());
if (!isValid) {
return "custom data does not match the schema";
}
}
}
return "";
};
this.isValidViewmodel = function(viewmodel) {
var viewmodelClass = viewmodel.getClass();
if (window[viewmodelClass] != undefined) {
// chack if custom data is valid
if (window[viewmodelClass].getCustomDataSchema != undefined && !oldff) {
var validate = new Ajv({}).compile(window[viewmodelClass].getCustomDataSchema());
var isValid = validate(viewmodel.getCustomData());
if (!isValid) {
return "custom data does not match the schema";
}
}
// check request connections
if (window[viewmodelClass].expectsConnection != undefined) {
var expectedConnections = window[viewmodelClass].expectsConnection();
var dataConnections = viewmodel.getDataConnections();
var selectionConnections = viewmodel.getSelectionConnections();
var connectionsOk = checkRequestToViewmodelConnections(dataConnections, selectionConnections, expectedConnections);
if (connectionsOk != "") {
return connectionsOk;
}
}
}
return "";
};
this.getHelp = function(className) {
if (window[className] != undefined && window[className].getHelp != undefined) {
return window[className].getHelp();
} else {
return "No help available for " + className;
}
};
this.getCustomDataSchema = function(className) {
if (window[className] != undefined && window[className].getCustomDataSchema != undefined) {
return window[className].getCustomDataSchema();
} else {
return undefined;
}
};
///////////////////// PRIVATE FUNCTIONS /////////////////////
function isSubsetOf(subset, set) {
var found = true;
for (var j = 0; j < subset.length && found; ++j) {
found = set.indexOf(subset[j]) != -1;
}
return found;
}
function findMandatoryOrOptional(expectedInterfaces) {
if (expectedInterfaces.mandatory != undefined) {
return expectedInterfaces.mandatory;
} else if (expectedInterfaces.optional != undefined) {
return expectedInterfaces.optional;
} else {
return undefined;
}
}
function checkRequestToViewmodelConnections(dataConnections, selectionConnections, expectedConnections) {
var expectedDataConnections = expectedConnections.dataConnections;
if (expectedDataConnections != undefined) {
if (expectedDataConnections.length == 0 && dataConnections.length > 0) {
return "no data connections expected";
}
for (var i = 0; i < dataConnections.length; ++i) {
var expectedConnectionIndex = Math.min(i, expectedDataConnections.length - 1);
var expectedConnection = expectedDataConnections[expectedConnectionIndex];
if (i >= expectedDataConnections.length && expectedConnectionIndex == expectedDataConnections.length - 1 && expectedConnection.multiple !== true) {
return "more data connections detected than expected";
}
var result = checkRequestToViewmodelConnection(dataConnections, selectionConnections, expectedConnection, dataConnections, i, "data connection");
if (result != "") {
return result;
}
}
if (expectedDataConnections[dataConnections.length] != undefined && (expectedDataConnections[dataConnections.length].optional == undefined || expectedDataConnections[dataConnections.length].optional == false)) {
return "missing non optional data connection";
}
}
var expectedSelectionConnections = expectedConnections.selectionConnections;
if (expectedSelectionConnections != undefined) {
if (expectedSelectionConnections.length == 0 && selectionConnections.length > 0) {
return "no selection connections expected";
}
for (var i = 0; i < selectionConnections.length; ++i) {
var expectedConnectionIndex = Math.min(i, expectedSelectionConnections.length - 1);
var expectedConnection = expectedSelectionConnections[expectedConnectionIndex];
if (i >= expectedDataConnections.length && expectedConnectionIndex == expectedSelectionConnections.length - 1 && expectedConnection.multiple !== true) {
return "more selection connections detected than expected";
}
var result = checkRequestToViewmodelConnection(dataConnections, selectionConnections, expectedConnection, selectionConnections, i, "selection connection");
if (result != "") {
return result;
}
if (expectedSelectionConnections[selectionConnections.length] != undefined && (expectedSelectionConnections[selectionConnections.length].optional == undefined || expectedSelectionConnections[selectionConnections.length].optional == false)) {
return "missing non optional selection connection";
}
}
}
return "";
}
function checkRequestToViewmodelConnection(dataConnections, selectionConnections, expectedConnection, connections, indexOfConnection, connectionType) {
if (expectedConnection.childOfDataConnection != undefined) {
if (dataConnections[expectedConnection.childOfDataConnection] == undefined || !hasPrefix(connections[indexOfConnection], dataConnections[expectedConnection.childOfDataConnection])) {
return connectionType + " " + indexOfConnection + " is not a child of data connection " + expectedConnection.childOfDataConnection;
}
}
var request = getRequestFromPath(connections[indexOfConnection]);
if (expectedConnection.element != undefined && expectedConnection.element != request.getData.element) {
return "wrong element found for " + connectionType + " " + indexOfConnection + ", expected " + expectedConnection.element;
}
if (expectedConnection.source != undefined && expectedConnection.source != request.getData.source) {
return "wrong source found for " + connectionType + " " + indexOfConnection + ", expected " + expectedConnection.source;
}
if (expectedConnection.filter == true && request.getData.filter == undefined) {
return "expected a filter for " + connectionType + " " + indexOfConnection;
}
if (expectedConnection.valueType != undefined) {
var helpDataElement = getHelpFromRequest(request).dataElement;
if (helpDataElement != undefined && expectedConnection.valueType.indexOf(helpDataElement.valueType) == -1) {
return "wrong value type for " + connectionType + " " + indexOfConnection + ", expected " + expectedConnection.valueType;
}
}
if (
expectedConnection.dataElementOfDataConnection != undefined && (
dataConnections[expectedConnection.dataElementOfDataConnection] == undefined ||
getHelpFromRequest(request).index != getHelpFromRequest(getRequestFromPath(dataConnections[expectedConnection.dataElementOfDataConnection])).index
)
) {
return connectionType + " " + indexOfConnection + " is not the same element as data connection " + expectedConnection.dataElementOfDataConnection;
}
return "";
}
function getRequestFromPath(p_path) {
var request = v_request[p_path[0]];
for (var i = 1; i < p_path.length; ++i) {
request = request.getData.children[p_path[i]];
}
return request;
}
function hasPrefix(path, prefix) {
for (var i = 0; i < prefix.length; ++i) {
if (path[i] == undefined || path[i] != prefix[i]) {
return false;
}
}
return true;
}
function getHelpFromRequest(request) {
var requestHash = getRequestHash(request);
if (v_cache[requestHash] != undefined) {
return v_cache[requestHash];
}
var result;
var bestIndex;
var bestScore = 0;
var source = request.getData.source;
if (v_help)
for (var i = 0; i < v_help.sources.length; ++i) {
if (v_help.sources[i].source == source) {
for (var j = 0; j < v_help.sources[i].dataElements.length; ++j) {
var score = isCorrectElementForRequest(v_help.sources[i].dataElements[j].dataElement, request);
if (score > bestScore) {
result = {
"index": j,
"dataElement": v_help.sources[i].dataElements[j].dataElement
};
bestScore = score;
}
}
}
}
if (bestScore == 0) {
result = {
"index": -1
}
}
v_cache[requestHash] = result;
return result;
}
function isCorrectElementForRequest(dataElement, request) {
if (dataElement.name != request.getData.element) {
return 0;
}
var score = 1;
var params = getParamTypes(request);
if (dataElement.parameters != undefined) {
for (var i = 0; i < dataElement.parameters.length; ++i) {
if (dataElement.parameters[i].typeDescriptor != undefined && dataElement.parameters[i].typeDescriptor.reference != undefined && dataElement.parameters[i].typeDescriptor.reference.typeName != undefined) {
if (params.indexOf(dataElement.parameters[i].typeDescriptor.reference.typeName) != -1) {
++score;
}
}
}
}
return score;
}
function getRequestHash(request) {
var hash = request.getData.source + "." + request.getData.element;
var params = getParamTypes(request);
for (var i = 0; i < params.length; ++i) {
hash += "." + params[i];
}
return hash;
}
function getParamTypes(request) {
var params = [];
if (request.getData.params != undefined) {
for (var i = 0; i < request.getData.params.length; ++i) {
params.push(request.getData.params[i].paramName);
}
}
params.sort();
return params;
}
}
//# sourceURL=GuiEditor\ViewModels\ViewModel_SanityChecker.js