diff options
author | 2016-08-31 16:47:33 +0800 | |
---|---|---|
committer | 2016-08-31 16:47:33 +0800 | |
commit | fa49e78cc199526a9e33b59c5194f8e3bf0f0952 (patch) | |
tree | 3478e867a8f304266dbceca6e992cceca410ede4 /winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-support-common.js | |
parent | 159d40f0011559c8f82338b29dca1bffd700f2c8 (diff) |
Add winery source code
Change-Id: I1c5088121d79b71098c3cba1996c6f784737532e
Issue-id: TOSCA-49
Signed-off-by: huangjian <huang.jian12@zte.com.cn>
Diffstat (limited to 'winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-support-common.js')
-rw-r--r-- | winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-support-common.js | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-support-common.js b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-support-common.js new file mode 100644 index 0000000..4e87f22 --- /dev/null +++ b/winery/org.eclipse.winery.topologymodeler/src/main/webapp/js/winery-support-common.js @@ -0,0 +1,330 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ + +/** + * Functions copied from winery-common.js to replace it in the long term + * + * Shared between topology modeler and repository + */ +define([], function() { + var xmlParser = new DOMParser(); + var VALUE_OF_NONE_CHOOSEN = "(none)"; // constant to indicate that nothing is chosen in a select2 + + return { + encodeId: encodeId, + getNamespaceAndLocalNameFromQName: getNamespaceAndLocalNameFromQName, + replaceDialogShownHookForOrionUpdate: replaceDialogShownHookForOrionUpdate, + writeCollectionDefinedByATextArea: writeCollectionDefinedByATextArea, + getDocument: getDocument, + + getURLFragmentOutOfFullQName: getURLFragmentOutOfFullQName, + makeArtifactTypeURLFromQName: makeArtifactTypeURLFromQName, + makeNodeTypeURLFromQName: makeNodeTypeURLFromQName, + makeRelationshipTypeURLFromQName: makeRelationshipTypeURLFromQName, + makeRelationshipTypeURLFromNSAndLocalName: makeRelationshipTypeURLFromNSAndLocalName, + + qname2href: qname2href, + + fetchSelect2DataAndInitSelect2: fetchSelect2DataAndInitSelect2, + removeItemFromSelect2Field: removeItemFromSelect2Field, + + checkXMLValidityAndShowErrorIfInvalid: checkXMLValidityAndShowErrorIfInvalid, + synchronizeNameAndType: synchronizeNameAndType, + + VALUE_OF_NONE_CHOOSEN: VALUE_OF_NONE_CHOOSEN + }; + + /** + * OriginalName: encodeID + */ + function encodeId(id) { + // the URL sent to the server should be the encoded id + id = encodeURIComponent(id); + // therefore, we have to encode it twice + id = encodeURIComponent(id); + return id; + } + + /** + * @param qname a QName in the form {namespace}localname + * @return { namespace: namespace, localname: localname } + */ + function getNamespaceAndLocalNameFromQName(qname) { + var i = qname.indexOf("}"); + var res = { + namespace : qname.substr(1,i-1), + localname : qname.substr(i+1) + }; + return res; + } + + /** + * Orion does not update content if field not fully shown + * therefore, we hook in into the "shown" event + */ + function replaceDialogShownHookForOrionUpdate(diag, orionAreaId, content) { + diag.off("shown.bs.modal"); + diag.on("shown.bs.modal", function() { + var area = window.winery.orionareas[orionAreaId]; + area.editor.setText(content); + area.fixEditorHeight(); + }); + } + + function getURLFragmentOutOfNSAndLocalName(nsAndLocalName) { + var res; + res = encodeID(nsAndLocalName.namespace); + res = res + "/"; + res = res + encodeID(nsAndLocalName.localname); + return res; + } + + /** + * Extracts an URL fragment of the form <encoded namespace>/<encoded id> out of a full QName + * + * @param qname a QName in the form {namespace}localname + */ + function getURLFragmentOutOfFullQName(qname) { + var d = getNamespaceAndLocalNameFromQName(qname); + return getURLFragmentOutOfNSAndLocalName(d); + } + + /** + * @param w the XMLwriter + * @param elementSet the set of HTML elements to write + * @param elementName the name of the wrapper element (e.g., "Requirements", "Policies") + */ + function writeCollectionDefinedByATextArea(w, elementSet, elementName) { + if (elementSet.length !== 0) { + w.writeStartElement(elementName); + elementSet.each(function(i, element) { + // XML contains element completely + // we do not have to parse reqorcap.children("div.id").children("span.id").text() or the span.name + var text = $(element).children("textarea").val(); + w.writeXML(text); + }); + w.writeEndElement(); + } + } + + function makeArtifactTypeURLFromQName(repoURL, qname) { + return repoURL + "/artifacttypes/" + getURLFragmentOutOfFullQName(qname) + "/"; + } + + function makeNodeTypeURLFromQName(repoURL, qname) { + return repoURL + "/nodetypes/" + getURLFragmentOutOfFullQName(qname) + "/"; + } + + function makeRelationshipTypeURLFromQName(repoURL, qname) { + return repoURL + "/relationshiptypes/" + getURLFragmentOutOfFullQName(qname) + "/"; + } + + function makeRelationshipTypeURLFromNSAndLocalName(repoURL, nsAndLocalName) { + return repoURL + "/relationshiptypes/" + getURLFragmentOutOfNSAndLocalName(nsAndLocalName) + "/"; + } + + /** + * functionality similar to org.eclipse.winery.common.Util.qname2href(String, Class<? extends TExtensibleElements>, QName) + */ + function qname2href(repositoryUrl, componentPathFragment, qname) { + var nsAndId = getNamespaceAndLocalNameFromQName(qname); + var absoluteURL = repositoryUrl + "/" + componentPathFragment + "/" + getURLFragmentOutOfNSAndLocalName(nsAndId); + var res = "<a target=\"_blank\" data-qname=\"" + qname + "\" href=\"" + absoluteURL + "\">" + nsAndId.localname + "</a>"; + return res; + } + + /** + * Inspired by + * + * @param field is the jquery field + * @param id_to_remove the id to remove + */ + function removeItemFromSelect2Field(field, id_to_remove) { + // nothing can be done currently + // see https://github.com/ivaynberg/select2/issues/535#issuecomment-30210641 for a disucssion + vShowNotification("The select field shows stale data. Refresh the page to get rid of that.") + } + + /** + * Fetches select2 data from the given URL and initializes the field provided by the fieldId + * + * Calls vShowError if something went wrong + * + * @param onSuccess (optional) + * @param allowAdditions (optional) if set to true, select2 is initalized with the functionality to allow additions during the search + */ + function fetchSelect2DataAndInitSelect2(fieldId, url, onSuccess, allowAdditions) { + $.ajax({ + url: url, + dataType: "json" + }).done(function (result) { + var params = {"data": result}; + if (typeof allowAdditions === "boolean") { + params.createSearchChoice = function(term) { + // enables creation of new namespaces + return {id:term, text:term}; + } + } + + // init select2 and select first item + $("#" + fieldId).select2(params); + if (result.length === 0) { + $("#" + fieldId).select2("val", null); + } else { + $("#" + fieldId).select2("val", result[0].id); + } + + if (typeof onSuccess === "function") { + onSuccess(); + } + }).fail(function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not fetch select2 data from " + url, jqXHR, errorThrown); + }); + + } + + + function getDocument(xmlString) { + var xmlDoc = xmlParser.parseFromString(xmlString, "text/xml"); + return xmlDoc; + } + + /** + * Checks given XML string for validity. If it's invalid, an error message is shown + * Relies on the current browser's XML handling returning a HTML document if something went wrong during parsing + * + * @return XMLdocument if XML is valid, false otherwise + */ + function checkXMLValidityAndShowErrorIfInvalid(xmlString) { + var doc = getDocument(xmlString); + var errorMsg = ""; + if (doc.firstChild.localName == "html") { + errorMsg = new XMLSerializer().serializeToString(doc); + } else { + // at Chrome, the error may be nested in the XML + + // quick hack, only "xhtml" is quered + function nsResolover(x) { + return "http://www.w3.org/1999/xhtml"; + } + + var element = doc.evaluate( '//x:parsererror', doc, nsResolover, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; + if (element !== null) { + errorMsg = new XMLSerializer().serializeToString(element); + } + } + + if (errorMsg !== "") { + vShowError(errorMsg); + return false; + } else { + return doc; + } + } + + /** + * Updates the XML in the orion editor based on the values given in the input fields. + * Shows error if XML is invalid + * + * Works only with SELECT2 fields + * + * @param idPrefix: (new|edit)${shortName}, derived names: [idPrefix]Name, [idPrefix]Id, Orion[idPrefix]XML + * @param hasIdField: whether the Id should be read and written + * @param selectFields: array of {attribute, fieldSuffix}, where attribute is a name of an attribute having a QName. + * Each select box is determined by #[idPrefix][fieldSuffix]. + * The select box content is converted to a QName and the result is written to the attribute [name] + * Default: {attribute: "type", fieldSuffix: "Type"} + * + * @return false if XML is invalid, true: an object if id/name/attribute1/attribute2/... (qname + attribute1FullQName: qname object)/xml (to be used in tmpl-${cssClassPrefix}) + * {id:id, name:name, type: "ns5:type", typeFullQName: "{http://www.example.org}type"} + */ + function synchronizeNameAndType(idPrefix, hasIdField, selectFields) { + if (typeof hasIdField === undefined) { + hasIdField = true; + } + if (typeof selectFields === undefined) { + selectFields = [{attribute: "type", fieldSuffix: "Type"}]; + } + + + var val = window.winery.orionareas["Orion" + idPrefix + "XML"].editor.getText(); + var xmlDoc = checkXMLValidityAndShowErrorIfInvalid(val); + if (xmlDoc) { + // handle name + var name = $("#" + idPrefix + "Name").val(); + // initialize result object + var res = { + name: name + }; + xmlDoc.firstChild.setAttribute("name", name); + + // write id and name to XML + if (hasIdField) { + var id = $("#" + idPrefix + "Id").val(); + if (!id) { + // TODO a checking should be done if the id exists + // probably not here, but at caller's side + id = name; + } + xmlDoc.firstChild.setAttribute("id", id); + res.id = id; + } + + // write each selectField to xml + // for that, we have to determine the QName + $(selectFields).each(function(i, m) { + var content = $("#" + idPrefix + m.fieldSuffix).select2("val"); + + if (content == VALUE_OF_NONE_CHOOSEN) { + // if nothing is chosen do not put it into the result + return; + } + + // determine qname of type + //getQNameOutOfFullQName(type, xmlDoc.firstChild) does not always work as xmlDoc.firstChild does not have ALL *available* namespace prefixes + var typeNSAndId = getNamespaceAndLocalNameFromQName(content); + var prefix = xmlDoc.firstChild.lookupPrefix(typeNSAndId.namespace); + if (!prefix) { + // we have to ask the repo for a prefix + $.ajax({ + type: "GET", + async: false, + "url": winery.repositoryURL + "/admin/namespaces/" + encodeID(typeNSAndId.namespace), + dataType: "text", + error: function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not determine prefix", jqXHR, errorThrown); + }, + success: function(resData, textStatus, jqXHR) { + prefix = resData; + } + }); + // new prefix fetched, xmlns attribute has to be written + xmlDoc.firstChild.setAttribute("xmlns:" + prefix, typeNSAndId.namespace); + } + var qname = prefix + ":" + typeNSAndId.localname; + res[m.attribute] = qname; + res[m.attribute + "FullQName"] = typeNSAndId; + xmlDoc.firstChild.setAttribute(m.attribute, qname); + }); + + var xml = new XMLSerializer().serializeToString(xmlDoc); + res.xml = xml; + + return res; + } else { + return false; + } + } + + + } +); |