Merge "Fix build errors in autorelease full clean build"
[vfc/nfvo/wfengine.git] / winery / org.eclipse.winery.repository / src / main / java / org / eclipse / winery / repository / Utils.java
1 /*******************************************************************************
2  * Copyright (c) 2012-2013 University of Stuttgart.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * and the Apache License 2.0 which both accompany this distribution,
6  * and are available at http://www.eclipse.org/legal/epl-v10.html
7  * and http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Contributors:
10  *     Oliver Kopp - initial API and implementation
11  *******************************************************************************/
12 package org.eclipse.winery.repository;
13
14 import java.io.BufferedInputStream;
15 import java.io.IOException;
16 import java.io.OutputStream;
17 import java.io.StringWriter;
18 import java.lang.reflect.Constructor;
19 import java.lang.reflect.InvocationTargetException;
20 import java.net.URI;
21 import java.net.URISyntaxException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.SortedSet;
27 import java.util.TreeSet;
28
29 import javax.ws.rs.WebApplicationException;
30 import javax.ws.rs.core.MediaType;
31 import javax.ws.rs.core.Response;
32 import javax.ws.rs.core.Response.Status;
33 import javax.ws.rs.core.Response.Status.Family;
34 import javax.ws.rs.core.StreamingOutput;
35 import javax.xml.bind.JAXBElement;
36 import javax.xml.bind.JAXBException;
37 import javax.xml.bind.Marshaller;
38 import javax.xml.namespace.QName;
39
40 import org.apache.taglibs.standard.functions.Functions;
41 import org.apache.tika.detect.Detector;
42 import org.apache.tika.metadata.Metadata;
43 import org.apache.tika.parser.AutoDetectParser;
44 import org.apache.xerces.xs.XSConstants;
45 import org.eclipse.winery.common.RepositoryFileReference;
46 import org.eclipse.winery.common.Util;
47 import org.eclipse.winery.common.ids.GenericId;
48 import org.eclipse.winery.common.ids.Namespace;
49 import org.eclipse.winery.common.ids.XMLId;
50 import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
51 import org.eclipse.winery.common.ids.definitions.imports.XSDImportId;
52 import org.eclipse.winery.model.tosca.TArtifactType;
53 import org.eclipse.winery.model.tosca.TConstraint;
54 import org.eclipse.winery.model.tosca.TEntityTemplate;
55 import org.eclipse.winery.model.tosca.TEntityType;
56 import org.eclipse.winery.model.tosca.TExtensibleElements;
57 import org.eclipse.winery.model.tosca.TNodeType;
58 import org.eclipse.winery.model.tosca.TPolicyType;
59 import org.eclipse.winery.model.tosca.TRelationshipType;
60 import org.eclipse.winery.repository.backend.BackendUtils;
61 import org.eclipse.winery.repository.backend.Repository;
62 import org.eclipse.winery.repository.datatypes.ids.admin.AdminId;
63 import org.eclipse.winery.repository.export.CSARExporter;
64 import org.eclipse.winery.repository.export.TOSCAExportUtil;
65 import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource;
66 import org.eclipse.winery.repository.resources.AbstractComponentsResource;
67 import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource;
68 import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypesResource;
69 import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypeResource;
70 import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypesResource;
71 import org.eclipse.winery.repository.resources.imports.xsdimports.XSDImportResource;
72 import org.slf4j.ext.XLogger;
73 import org.slf4j.ext.XLoggerFactory;
74 import org.w3c.dom.Element;
75
76 import com.fasterxml.jackson.core.JsonProcessingException;
77 import com.fasterxml.jackson.databind.ObjectMapper;
78 import com.fasterxml.jackson.databind.node.ArrayNode;
79 import com.fasterxml.jackson.databind.node.ObjectNode;
80 import com.sun.jersey.api.client.Client;
81 import com.sun.jersey.api.client.ClientResponse;
82 import com.sun.jersey.api.client.WebResource;
83
84 /**
85  * Contains utility functionality concerning with everything that is
86  * <em>not</em> related only to the repository, but more. For instance, resource
87  * functionality. Utility functionality for the repository is contained at
88  * {@link BackendUtils}
89  */
90 public class Utils {
91         
92         private static final XLogger logger = XLoggerFactory.getXLogger(Utils.class);
93         
94         
95         public static URI createURI(String uri) {
96                 try {
97                         return new URI(uri);
98                 } catch (URISyntaxException e) {
99                         throw new IllegalStateException();
100                 }
101         }
102         
103         
104         // RegExp inspired by http://stackoverflow.com/a/5396246/873282
105         // NameStartChar without ":"
106         // stackoverflow: -dfff, standard: d7fff
107         private static final String RANGE_NCNAMESTARTCHAR = "A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02ff\\u0370-\\u037d" + "\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\ud7ff" + "\\uf900-\\ufdcf\\ufdf0-\\ufffd\\x10000-\\xEFFFF";
108         private static final String REGEX_NCNAMESTARTCHAR = "[" + Utils.RANGE_NCNAMESTARTCHAR + "]";
109         
110         private static final String RANGE_NCNAMECHAR = Utils.RANGE_NCNAMESTARTCHAR + "\\-\\.0-9\\u00b7\\u0300-\\u036f\\u203f-\\u2040";
111         private static final String REGEX_INVALIDNCNAMESCHAR = "[^" + Utils.RANGE_NCNAMECHAR + "]";
112         
113         
114         /**
115          * Creates a (valid) XML ID (NCName) based on the passed name
116          * 
117          * Valid NCNames: http://www.w3.org/TR/REC-xml-names/#NT-NCName /
118          * http://www.w3.org/TR/xml/#NT-Name http://www.w3.org/TR/xml/#NT-Name
119          * 
120          */
121         public static XMLId createXMLid(String name) {
122                 return new XMLId(Utils.createXMLidAsString(name), false);
123         }
124         
125         /**
126          * Creates a (valid) XML ID (NCName) based on the passed name
127          * 
128          * Valid NCNames: http://www.w3.org/TR/REC-xml-names/#NT-NCName /
129          * http://www.w3.org/TR/xml/#NT-Name http://www.w3.org/TR/xml/#NT-Name
130          * 
131          * TODO: this method seems to be equal to {@link
132          * org.eclipse.winery.common.Util.makeNCName(String)}. The methods should be
133          * merged into one.
134          * 
135          */
136         public static String createXMLidAsString(String name) {
137                 String id = name;
138                 if (!id.substring(0, 1).matches(Utils.REGEX_NCNAMESTARTCHAR)) {
139                         id = "_".concat(id);
140                 }
141                 // id starts with a valid character
142                 
143                 // before we wipe out all invalid characters, we do a readable
144                 // replacement for appropriate characters
145                 id = id.replace(' ', '_');
146                 
147                 // keep length of ID, only wipe out invalid characters
148                 // alternative: replace invalid characters by URLencoded version. As the
149                 // ID is visible only in the URL, this quick hack should be OK
150                 // ID is visible only in the URL, this quick hack should be OK
151                 id = id.replaceAll(Utils.REGEX_INVALIDNCNAMESCHAR, "_");
152                 
153                 return id;
154         }
155         
156         /**
157          * Returns the plain XML for the selected resource
158          * 
159          * @param uri
160          */
161         public static Response getDefinitionsOfSelectedResource(final AbstractComponentInstanceResource resource, final URI uri) {
162                 final TOSCAExportUtil exporter = new TOSCAExportUtil();
163                 StreamingOutput so = new StreamingOutput() {
164                         
165                         @Override
166                         public void write(OutputStream output) throws IOException, WebApplicationException {
167                                 Map<String, Object> conf = new HashMap<>();
168                                 conf.put(TOSCAExportUtil.ExportProperties.REPOSITORY_URI.toString(), uri);
169                                 try {
170                                         exporter.exportTOSCA(resource.getId(), output, conf);
171                                 } catch (JAXBException e) {
172                                         throw new WebApplicationException(e);
173                                 }
174                                 output.close();
175                         }
176                 };
177                 /*
178                  * this code is for offering a download action // Browser offers save as
179                  * // .tosca is more or less needed for debugging, only a CSAR makes
180                  * sense. // Therefore, we want to have the xml opened in the browser.
181                  * StringBuilder sb = new StringBuilder();
182                  * sb.append("attachment;filename=\"");
183                  * sb.append(resource.getXmlId().getEncoded()); sb.append(" - ");
184                  * sb.append(resource.getNamespace().getEncoded()); sb.append(".xml");
185                  * sb.append("\""); return Response.ok().header("Content-Disposition",
186                  * sb
187                  * .toString()).type(MediaType.APPLICATION_XML_TYPE).entity(so).build();
188                  */
189                 return Response.ok().type(MediaType.APPLICATION_XML).entity(so).build();
190         }
191         
192         public static Response getCSARofSelectedResource(final AbstractComponentInstanceResource resource) {
193                 final CSARExporter exporter = new CSARExporter();
194                 StreamingOutput so = new StreamingOutput() {
195                         
196                         @Override
197                         public void write(OutputStream output) throws IOException, WebApplicationException {
198                                 try {
199                                         exporter.writeCSAR(resource.getId(), output);
200                                 } catch (Exception e) {
201                                         throw new WebApplicationException(e);
202                                 }
203                         }
204                 };
205                 StringBuilder sb = new StringBuilder();
206                 sb.append("attachment;filename=\"");
207                 sb.append(resource.getXmlId().getEncoded());
208                 sb.append(org.eclipse.winery.repository.Constants.SUFFIX_CSAR);
209                 sb.append("\"");
210                 return Response.ok().header("Content-Disposition", sb.toString()).type(org.eclipse.winery.common.constants.MimeTypes.MIMETYPE_ZIP).entity(so).build();
211         }
212         
213         /**
214          * @return Singular type name for the given resource. E.g.,
215          *         "ServiceTemplateResource" gets "ServiceTemplate"
216          */
217         public static String getTypeForInstance(Class<? extends AbstractComponentInstanceResource> resClass) {
218                 String res = resClass.getName();
219                 // Everything between the last "." and before "Resource" is the Type
220                 int dotIndex = res.lastIndexOf('.');
221                 assert (dotIndex >= 0);
222                 return res.substring(dotIndex + 1, res.length() - "Resource".length());
223         }
224         
225         /**
226          * @return Singular type name for the given id. E.g., "ServiceTemplateId"
227          *         gets "ServiceTemplate"
228          */
229         public static String getTypeForAdminId(Class<? extends AdminId> idClass) {
230                 return Util.getEverythingBetweenTheLastDotAndBeforeId(idClass);
231         }
232         
233         /**
234          * @return Singular type name for given AbstractComponentsResource. E.g,
235          *         "ServiceTemplatesResource" gets "ServiceTemplate"
236          */
237         public static String getTypeForComponentContainer(Class<? extends AbstractComponentsResource> containerClass) {
238                 String res = containerClass.getName();
239                 // Everything between the last "." and before "sResource" is the Type
240                 int dotIndex = res.lastIndexOf('.');
241                 assert (dotIndex >= 0);
242                 return res.substring(dotIndex + 1, res.length() - "sResource".length());
243         }
244         
245         @SuppressWarnings("unchecked")
246         public static Class<? extends TOSCAComponentId> getComponentIdClass(String idClassName) {
247                 String pkg = "org.eclipse.winery.common.ids.definitions.";
248                 if (idClassName.contains("Import")) {
249                         // quick hack to handle imports, which reside in their own package
250                         pkg = pkg + "imports.";
251                 }
252                 String fullClassName = pkg + idClassName;
253                 try {
254                         return (Class<? extends TOSCAComponentId>) Class.forName(fullClassName);
255                 } catch (ClassNotFoundException e) {
256                         // quick hack for Ids local to winery repository
257                         try {
258                                 fullClassName = "org.eclipse.winery.repository.datatypes.ids.admin." + idClassName;
259                                 return (Class<? extends TOSCAComponentId>) Class.forName(fullClassName);
260                         } catch (ClassNotFoundException e2) {
261                                 String errorMsg = "Could not find id class for component container, " + fullClassName;
262                                 Utils.logger.error(errorMsg);
263                                 throw new IllegalStateException(errorMsg);
264                         }
265                 }
266         }
267         
268         /**
269          * Returns a class object for ids of components nested in the given
270          * AbstractComponentsResource
271          */
272         public static Class<? extends TOSCAComponentId> getComponentIdClassForComponentContainer(Class<? extends AbstractComponentsResource> containerClass) {
273                 // the name of the id class is the type + "Id"
274                 String idClassName = Utils.getTypeForComponentContainer(containerClass) + "Id";
275                 
276                 return Utils.getComponentIdClass(idClassName);
277         }
278         
279         public static Class<? extends TOSCAComponentId> getComponentIdClassForTExtensibleElements(Class<? extends TExtensibleElements> clazz) {
280                 // we assume that the clazzName always starts with a T.
281                 // Therefore, we fetch everything after the last dot (plus offest 1)
282                 String idClassName = clazz.getName();
283                 int dotIndex = idClassName.lastIndexOf('.');
284                 assert (dotIndex >= 0);
285                 idClassName = idClassName.substring(dotIndex + 2) + "Id";
286                 
287                 return Utils.getComponentIdClass(idClassName);
288         }
289         
290         
291         private static final String slashEncoded = Util.URLencode("/");
292         
293         
294         public static String getURLforPathInsideRepo(String pathInsideRepo) {
295                 // first encode the whole string
296                 String res = Util.URLencode(pathInsideRepo);
297                 // issue: "/" is also encoded. This has to be undone:
298                 res = res.replaceAll(Utils.slashEncoded, "/");
299                 return res;
300         }
301         
302         
303         /**
304          * Shared object to map JSONs
305          */
306         public static final ObjectMapper mapper = new ObjectMapper();
307         
308         
309         public static String Object2JSON(Object o) {
310                 String res;
311                 try {
312                         res = Utils.mapper.writeValueAsString(o);
313                 } catch (Exception e) {
314                         Utils.logger.error(e.getMessage(), e);
315                         return null;
316                 }
317                 return res;
318         }
319         
320         @SuppressWarnings("unchecked")
321         public static Class<? extends GenericId> getGenericIdClassForType(String typeIdType) {
322                 Class<? extends GenericId> res;
323                 // quick hack - we only need definitions right now
324                 String pkg = "org.eclipse.winery.repository.datatypes.ids.definitions.";
325                 String className = typeIdType;
326                 className = pkg + className;
327                 try {
328                         res = (Class<? extends GenericId>) Class.forName(className);
329                 } catch (ClassNotFoundException e) {
330                         Utils.logger.error("Could not find id class for id type", e);
331                         res = null;
332                 }
333                 return res;
334         }
335         
336         /**
337          * @return the absolute path for the given id
338          */
339         public static String getAbsoluteURL(GenericId id) {
340                 return Prefs.INSTANCE.getResourcePath() + "/" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(id));
341         }
342         
343         /**
344          * @param baseURI the URI from which the path should start
345          * @param id the generic id to resolve
346          * 
347          * @return the relative path for the given id
348          */
349         public static String getRelativeURL(URI baseURI, GenericId id) {
350                 String absolutePath = Prefs.INSTANCE.getResourcePath() + "/" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(id));
351                 return baseURI.relativize(URI.create(absolutePath)).toString();
352         }
353         
354         /**
355          * @return the absolute path for the given id
356          */
357         public static String getAbsoluteURL(RepositoryFileReference ref) {
358                 return Prefs.INSTANCE.getResourcePath() + "/" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(ref));
359         }
360         
361         public static URI getAbsoluteURI(GenericId id) {
362                 return Utils.createURI(Utils.getAbsoluteURL(id));
363         }
364         
365         public static String doubleEscapeHTMLAndThenConvertNL2BR(String txt) {
366                 String res = Functions.escapeXml(txt);
367                 res = Functions.escapeXml(res);
368                 res = res.replaceAll("\\n", "<br/>");
369                 return res;
370         }
371         
372         /**
373          * This method is similar to {@link
374          * org.eclipse.winery.common.Util.qname2href()}, but treats winery's
375          * internal ID model instead of the global TOSCA model
376          * 
377          * @param id the id to create an <code>a href</code> element for
378          * @return an <code>a</code> HTML element pointing to the given id
379          */
380         public static String getHREF(TOSCAComponentId id) {
381                 String res = "<a href=\"" + Utils.getAbsoluteURL(id) + "\">" + Functions.escapeXml(id.getXmlId().getDecoded()) + "</a>";
382                 return res;
383         }
384         
385         public static String artifactTypeQName2href(QName qname) {
386                 return Util.qname2href(Prefs.INSTANCE.getResourcePath(), TArtifactType.class, qname);
387         }
388         
389         public static String nodeTypeQName2href(QName qname) {
390                 return Util.qname2href(Prefs.INSTANCE.getResourcePath(), TNodeType.class, qname);
391         }
392         
393         public static String relationshipTypeQName2href(QName qname) {
394                 return Util.qname2href(Prefs.INSTANCE.getResourcePath(), TRelationshipType.class, qname);
395         }
396         
397         public static String policyTypeQName2href(QName qname) {
398                 return Util.qname2href(Prefs.INSTANCE.getResourcePath(), TPolicyType.class, qname);
399         }
400         
401         /**
402          * Returns the middle part of the package name or the JSP location
403          * 
404          * @param type the type
405          * @param separator the separator to be used, "." or "/"
406          * @return string which can be used "in the middle" of a package or of a
407          *         path to a JSP
408          */
409         public static String getIntermediateLocationStringForType(String type, String separator) {
410                 String location;
411                 if (type.contains("ServiceTemplate")) {
412                         location = "servicetemplates";
413                 } else {
414                         if (type.contains("TypeImplementation")) {
415                                 location = "entitytypeimplementations";
416                         } else if (type.contains("Type")) {
417                                 location = "entitytypes";
418                         } else if (type.contains("Import")) {
419                                 location = "imports";
420                         } else {
421                                 assert (type.contains("Template"));
422                                 location = "entitytemplates";
423                         }
424                         // location now is the super pkg, we have to add a pkg of the type
425                         location = location + separator + type.toLowerCase() + "s";
426                 }
427                 return location;
428         }
429         
430         /**
431          * Required by topologyedit.jsp
432          * 
433          * @return all known nodetype resources
434          */
435         public static Collection<NodeTypeResource> getAllNodeTypeResources() {
436                 @SuppressWarnings("unchecked")
437                 Collection<NodeTypeResource> res = (Collection<NodeTypeResource>) (Collection<?>) new NodeTypesResource().getAll();
438                 return res;
439         }
440         
441         /**
442          * Required by topologyedit.jsp
443          * 
444          * @return all known relation ship type resources
445          */
446         public static Collection<RelationshipTypeResource> getAllRelationshipTypeResources() {
447                 @SuppressWarnings("unchecked")
448                 Collection<RelationshipTypeResource> res = (Collection<RelationshipTypeResource>) (Collection<?>) new RelationshipTypesResource().getAll();
449                 return res;
450         }
451         
452         /**
453          * @return the path to the Winery topology modeler. Required by
454          *         functions.tld
455          */
456         public static String getWineryTopologyModelerPath() {
457                 return Prefs.INSTANCE.getWineryTopologyModelerPath();
458         }
459         
460         /**
461          * Detect the mime type of the stream. The stream is marked at the beginning
462          * and reset at the end
463          * 
464          * @param is the stream
465          * @param fileName the fileName of the file belonging to the stream
466          */
467         public static String getMimeType(BufferedInputStream bis, String fn) throws IOException {
468                 AutoDetectParser parser = new AutoDetectParser();
469                 Detector detector = parser.getDetector();
470                 Metadata md = new Metadata();
471                 md.add(Metadata.RESOURCE_NAME_KEY, fn);
472                 org.apache.tika.mime.MediaType mediaType = detector.detect(bis, md);
473                 return mediaType.toString();
474         }
475         
476         
477         private static final MediaType MEDIATYPE_APPLICATION_OCTET_STREAM = MediaType.valueOf("application/octet-stream");
478         
479         
480         /**
481          * Fixes the mediaType if it is too vague (such as application/octet-stream)
482          * 
483          * @return a more fitting MediaType or the original one if it is appropriate
484          *         enough
485          */
486         public static MediaType getFixedMimeType(BufferedInputStream is, String fileName, MediaType mediaType) {
487                 if (mediaType.equals(Utils.MEDIATYPE_APPLICATION_OCTET_STREAM)) {
488                         // currently, we fix application/octet-stream only
489                         
490                         // TODO: instead of using apache tika, we could hve a user-configured map storing
491                         //  * media type
492                         //  * file extension
493                         
494                         try {
495                                 return MediaType.valueOf(Utils.getMimeType(is, fileName));
496                         } catch (Exception e) {
497                                 Utils.logger.debug("Could not determine mimetype for " + fileName, e);
498                                 // just keep the old one
499                                 return mediaType;
500                         }
501                 } else {
502                         return mediaType;
503                 }
504         }
505         
506         /**
507          * Converts the given object to XML.
508          * 
509          * Used in cases the given element is not annotated with @XmlRoot
510          * 
511          * We cannot use {@literal Class<? extends TExtensibleElements>} as, for
512          * instance, {@link TConstraint} does not inherit from
513          * {@link TExtensibleElements}
514          * 
515          * @param clazz the Class of the passed object, required if obj is null
516          * @param obj the object to serialize
517          */
518         public static <T extends Object> Response getXML(Class<T> clazz, T obj) {
519                 // see commit ab4b5c547619c058990 for an implementation using getJAXBElement,
520                 // which can be directly passed as entity
521                 // the issue is that we want to have a *formatted* XML
522                 // Therefore, we serialize "by hand".
523                 String xml = Utils.getXMLAsString(clazz, obj, false);
524                 
525                 return Response.ok().type(MediaType.TEXT_XML).entity(xml).build();
526         }
527         
528         public static <T extends Object> String getXMLAsString(Class<T> clazz, T obj, boolean includeProcessingInstruction) {
529                 JAXBElement<T> rootElement = Util.getJAXBElement(clazz, obj);
530                 Marshaller m = JAXBSupport.createMarshaller(includeProcessingInstruction);
531                 StringWriter w = new StringWriter();
532                 try {
533                         m.marshal(rootElement, w);
534                 } catch (JAXBException e) {
535                         Utils.logger.error("Could not put content to string", e);
536                         throw new IllegalStateException(e);
537                 }
538                 String res = w.toString();
539                 return res;
540         }
541         
542         public static String getXMLAsString(Object obj) {
543                 if (obj instanceof Element) {
544                         // in case the object is a DOM element, we use the DOM functionality
545                         return Util.getXMLAsString((Element) obj);
546                 } else {
547                         return Utils.getXMLAsString(obj, false);
548                 }
549         }
550         
551         public static <T extends Object> String getXMLAsString(T obj, boolean includeProcessingInstruction) {
552                 if (obj == null) {
553                         return "";
554                 }
555                 @SuppressWarnings("unchecked")
556                 Class<T> clazz = (Class<T>) obj.getClass();
557                 return Utils.getXMLAsString(clazz, obj, includeProcessingInstruction);
558         }
559         
560         public static String getAllXSDElementDefinitionsForTypeAheadSelection() {
561                 Utils.logger.entry();
562                 try {
563                         return Utils.getAllXSDefinitionsForTypeAheadSelection(XSConstants.ELEMENT_DECLARATION);
564                 } finally {
565                         Utils.logger.exit();
566                 }
567         }
568         
569         public static String getAllXSDTypeDefinitionsForTypeAheadSelection() {
570                 Utils.logger.entry();
571                 try {
572                         return Utils.getAllXSDefinitionsForTypeAheadSelection(XSConstants.TYPE_DEFINITION);
573                 } finally {
574                         Utils.logger.exit();
575                 }
576         }
577         
578         public static String getAllXSDefinitionsForTypeAheadSelection(short type) {
579                 SortedSet<XSDImportId> allImports = Repository.INSTANCE.getAllTOSCAComponentIds(XSDImportId.class);
580                 
581                 Map<Namespace, Collection<String>> data = new HashMap<Namespace, Collection<String>>();
582                 
583                 for (XSDImportId id : allImports) {
584                         XSDImportResource resource = new XSDImportResource(id);
585                         Collection<String> allLocalNames = resource.getAllDefinedLocalNames(type);
586                         
587                         Collection<String> list;
588                         if ((list = data.get(id.getNamespace())) == null) {
589                                 // list does not yet exist
590                                 list = new ArrayList<String>();
591                                 data.put(id.getNamespace(), list);
592                         }
593                         assert (list != null);
594                         
595                         list.addAll(allLocalNames);
596                 }
597                 
598                 ArrayNode rootNode = Utils.mapper.createArrayNode();
599                 
600                 // ensure ordering in JSON object
601                 Collection<Namespace> allns = new TreeSet<Namespace>();
602                 allns.addAll(data.keySet());
603                 
604                 for (Namespace ns : allns) {
605                         Collection<String> localNames = data.get(ns);
606                         if (!localNames.isEmpty()) {
607                                 ObjectNode groupEntry = Utils.mapper.createObjectNode();
608                                 rootNode.add(groupEntry);
609                                 groupEntry.put("text", ns.getDecoded());
610                                 ArrayNode children = Utils.mapper.createArrayNode();
611                                 groupEntry.put("children", children);
612                                 Collection<String> sortedLocalNames = new TreeSet<String>();
613                                 sortedLocalNames.addAll(localNames);
614                                 for (String localName : sortedLocalNames) {
615                                         String value = "{" + ns.getDecoded() + "}" + localName;
616                                         String text = localName;
617                                         ObjectNode o = Utils.mapper.createObjectNode();
618                                         o.put("text", text);
619                                         o.put("value", value);
620                                         children.add(o);
621                                 }
622                         }
623                 }
624                 
625                 try {
626                         return Utils.mapper.writeValueAsString(rootNode);
627                 } catch (JsonProcessingException e) {
628                         throw new IllegalStateException("Could not create JSON", e);
629                 }
630         }
631         
632         public static Response getResponseForException(Exception e) {
633                 String msg;
634                 if (e.getCause() != null) {
635                         msg = e.getCause().getMessage();
636                 } else {
637                         msg = e.getMessage();
638                 }
639                 Response res = Response.status(Status.INTERNAL_SERVER_ERROR).entity(msg).build();
640                 return res;
641         }
642         
643         /**
644          * Returns the stored type for the given template
645          * 
646          * Goes to the repository to retrieve stored data
647          * 
648          * @param template the template to determine the type for
649          */
650         // we suppress "unchecked" as we use Class.forName
651         @SuppressWarnings("unchecked")
652         public static TEntityType getTypeForTemplate(TEntityTemplate template) {
653                 QName type = template.getType();
654                 
655                 // Possibilities:
656                 // a) try all possibly types whether an appropriate QName exists
657                 // b) derive type class from template class. Determine appropriate resource afterwards.
658                 // We go for b)
659                 
660                 String instanceResourceClassName = template.getClass().toString();
661                 int idx = instanceResourceClassName.lastIndexOf('.');
662                 // get everything from ".T", where "." is the last dot
663                 instanceResourceClassName = instanceResourceClassName.substring(idx + 2);
664                 // strip off "Template"
665                 instanceResourceClassName = instanceResourceClassName.substring(0, instanceResourceClassName.length() - "Template".length());
666                 // add "Type"
667                 instanceResourceClassName += "Type";
668                 
669                 // an id is required to instantiate the resource
670                 String idClassName = "org.eclipse.winery.common.ids.definitions." + instanceResourceClassName + "Id";
671                 
672                 String packageName = "org.eclipse.winery.repository.resources.entitytypes." + instanceResourceClassName.toLowerCase() + "s";
673                 // convert from NodeType to NodeTypesResource
674                 instanceResourceClassName += "Resource";
675                 instanceResourceClassName = packageName + "." + instanceResourceClassName;
676                 
677                 Utils.logger.debug("idClassName: {}", idClassName);
678                 Utils.logger.debug("className: {}", instanceResourceClassName);
679                 
680                 // Get instance of id class having "type" as id
681                 Class<? extends TOSCAComponentId> idClass;
682                 try {
683                         idClass = (Class<? extends TOSCAComponentId>) Class.forName(idClassName);
684                 } catch (ClassNotFoundException e) {
685                         throw new IllegalStateException("Could not determine id class", e);
686                 }
687                 Constructor<? extends TOSCAComponentId> idConstructor;
688                 try {
689                         idConstructor = idClass.getConstructor(QName.class);
690                 } catch (NoSuchMethodException | SecurityException e) {
691                         throw new IllegalStateException("Could not get QName id constructor", e);
692                 }
693                 TOSCAComponentId typeId;
694                 try {
695                         typeId = idConstructor.newInstance(type);
696                 } catch (InstantiationException | IllegalAccessException
697                                 | IllegalArgumentException | InvocationTargetException e) {
698                         throw new IllegalStateException("Could not instantiate type", e);
699                 }
700                 
701                 // now instantiate the resource, where the type belongs to
702                 Class<? extends AbstractComponentInstanceResource> instanceResourceClass;
703                 try {
704                         instanceResourceClass = (Class<? extends AbstractComponentInstanceResource>) Class.forName(instanceResourceClassName);
705                 } catch (ClassNotFoundException e) {
706                         throw new IllegalStateException("Could not determine component instance resource class", e);
707                 }
708                 Constructor<? extends AbstractComponentInstanceResource> resConstructor;
709                 try {
710                         resConstructor = instanceResourceClass.getConstructor(typeId.getClass());
711                 } catch (NoSuchMethodException | SecurityException e) {
712                         throw new IllegalStateException("Could not get contructor", e);
713                 }
714                 AbstractComponentInstanceResource typeResource;
715                 try {
716                         typeResource = resConstructor.newInstance(typeId);
717                 } catch (InstantiationException | IllegalAccessException
718                                 | IllegalArgumentException | InvocationTargetException e) {
719                         throw new IllegalStateException("Could not instantiate resoruce", e);
720                 }
721                 
722                 // read the data from the resource and store it
723                 TEntityType entityType = (TEntityType) typeResource.getElement();
724                 
725                 return entityType;
726         }
727         
728         /**
729          * referenced by functions.tld
730          */
731         public static Boolean isContainerLocallyAvailable() {
732                 return Prefs.INSTANCE.isContainerLocallyAvailable();
733         }
734         
735         /**
736          * referenced by functions.tld
737          * 
738          * We need the bridge as functions (at tld) require a static method. We did
739          * not want to put two methods in Prefs and therefore, we put the method
740          * here.
741          */
742         public static Boolean isRestDocDocumentationAvailable() {
743                 return Prefs.INSTANCE.isRestDocDocumentationAvailable();
744         }
745         
746         public static boolean isSuccessFulResponse(Response res) {
747                 return Status.fromStatusCode(res.getStatus()).getFamily().equals(Family.SUCCESSFUL);
748         }
749         
750         /**
751          * Converts the given String to an integer. Fallback if String is a float.
752          * If String is an invalid number, "0" is returned
753          */
754         public static int convertStringToInt(String number) {
755                 int intTop = 0;
756                 try {
757                         intTop = Integer.parseInt(number);
758                 } catch (NumberFormatException e) {
759                         try {
760                                 float floatTop = Float.parseFloat(number);
761                                 intTop = Math.round(floatTop);
762                         } catch (NumberFormatException e2) {
763                                 // do nothing
764                         }
765                 }
766                 
767                 return intTop;
768         }
769         
770         /**
771          * Checks whether a given resource (with absolute URL!) is available with a
772          * HEAD request on it.
773          */
774         public static boolean isResourceAvailable(String path) {
775                 Client client = Client.create();
776                 WebResource wr = client.resource(path);
777                 boolean res;
778                 try {
779                         ClientResponse response = wr.head();
780                         res = (response.getClientResponseStatus().getFamily().equals(Family.SUCCESSFUL));
781                 } catch (com.sun.jersey.api.client.ClientHandlerException ex) {
782                         // In the case of a java.net.ConnectException, return false
783                         res = false;
784                 }
785                 return res;
786         }
787 }