summaryrefslogtreecommitdiffstats
path: root/winery/org.eclipse.winery.repository.client/src
diff options
context:
space:
mode:
Diffstat (limited to 'winery/org.eclipse.winery.repository.client/src')
-rw-r--r--winery/org.eclipse.winery.repository.client/src/main/java/META-INF/MANIFEST.MF3
-rw-r--r--winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/IWineryRepositoryClient.java56
-rw-r--r--winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/WineryRepositoryClient.java746
-rw-r--r--winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/WineryRepositoryClientFactory.java20
-rw-r--r--winery/org.eclipse.winery.repository.client/src/main/resources/TOSCA-v1.0.xsd791
-rw-r--r--winery/org.eclipse.winery.repository.client/src/test/java/META-INF/MANIFEST.MF3
-rw-r--r--winery/org.eclipse.winery.repository.client/src/test/java/org/eclipse/winery/repository/client/TestWineryRepositoryClient.java144
7 files changed, 1763 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.repository.client/src/main/java/META-INF/MANIFEST.MF b/winery/org.eclipse.winery.repository.client/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..254272e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository.client/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
diff --git a/winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/IWineryRepositoryClient.java b/winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/IWineryRepositoryClient.java
new file mode 100644
index 0000000..f53aca9
--- /dev/null
+++ b/winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/IWineryRepositoryClient.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 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
+ *******************************************************************************/
+package org.eclipse.winery.repository.client;
+
+import org.eclipse.winery.common.interfaces.IWineryRepository;
+
+public interface IWineryRepositoryClient extends IWineryRepository {
+
+ /**
+ * Adds an URI to the list of known repositories
+ *
+ * SIDE EFFECT: If currently no primary repository is defined, the given
+ * repository is used as primary repository
+ *
+ * @param uri the URI of the repository
+ */
+ void addRepository(String uri);
+
+ /**
+ * Get the currently defined primary repository
+ */
+ String getPrimaryRepository();
+
+ /**
+ * Sets the primary repository
+ *
+ * SIDE EFFECT: If the repository is not known as general repository (via
+ * addRepository), the given repository is added to the list of known
+ * repositories
+ *
+ * @param uri
+ */
+ void setPrimaryRepository(String uri);
+
+ /**
+ * Checks whether the primary repository is available to be used. Typically,
+ * this method should return "true". In case of network or server failures,
+ * the result is "false". Note that the availability may change over time
+ * and also a repository might become unavailable during querying it.
+ *
+ * This method also returns "false" if no primary repository is set. For
+ * instance, this is the case of no repository is registered at the client.
+ *
+ * @return true if the repository is reachable over network, false otherwise
+ */
+ boolean primaryRepositoryAvailable();
+}
diff --git a/winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/WineryRepositoryClient.java b/winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/WineryRepositoryClient.java
new file mode 100644
index 0000000..216c623
--- /dev/null
+++ b/winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/WineryRepositoryClient.java
@@ -0,0 +1,746 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 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
+ *******************************************************************************/
+package org.eclipse.winery.repository.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.common.beans.NamespaceIdOptionalName;
+import org.eclipse.winery.common.constants.MimeTypes;
+import org.eclipse.winery.common.ids.GenericId;
+import org.eclipse.winery.common.ids.IdUtil;
+import org.eclipse.winery.common.ids.definitions.TOSCAComponentId;
+import org.eclipse.winery.common.interfaces.QNameAlreadyExistsException;
+import org.eclipse.winery.common.interfaces.QNameWithName;
+import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition;
+import org.eclipse.winery.model.tosca.TDefinitions;
+import org.eclipse.winery.model.tosca.TEntityType;
+import org.eclipse.winery.model.tosca.TExtensibleElements;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.client.urlconnection.HttpURLConnectionFactory;
+import com.sun.jersey.client.urlconnection.URLConnectionClientHandler;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+public final class WineryRepositoryClient implements IWineryRepositoryClient {
+
+ private static final Logger logger = LoggerFactory.getLogger(WineryRepositoryClient.class);
+
+ // switch off validation, currently causes more trouble than it brings
+ private static final boolean VALIDATING = false;
+
+ private final Collection<String> knownURIs = new HashSet<String>();
+ private final Collection<WebResource> repositoryResources = new HashSet<WebResource>();
+ private final Client client;
+ private final ObjectMapper mapper = new ObjectMapper();
+
+ private final Map<Class<? extends TEntityType>, Map<QName, TEntityType>> entityTypeDataCache;
+
+ private final Map<GenericId, String> nameCache;
+ private static final int MAX_NAME_CACHE_SIZE = 1000;
+
+ private String primaryRepository = null;
+ private WebResource primaryWebResource = null;
+
+ // thread-safe JAXB as inspired by https://jaxb.java.net/guide/Performance_and_thread_safety.html
+ // The other possibility: Each subclass sets JAXBContext.newInstance(theSubClass.class); in its static {} part.
+ // This seems to be more complicated than listing all subclasses in initContext
+ public final static JAXBContext context = WineryRepositoryClient.initContext();
+
+ // schema aware document builder
+ private final DocumentBuilder toscaDocumentBuilder;
+
+
+ // taken from http://stackoverflow.com/a/15253142/873282
+ private static class ConnectionFactory implements HttpURLConnectionFactory {
+
+ Proxy proxy;
+
+
+ private void initializeProxy() {
+ this.proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8888));
+ }
+
+ @Override
+ public HttpURLConnection getHttpURLConnection(URL url) throws IOException {
+ this.initializeProxy();
+ return (HttpURLConnection) url.openConnection(this.proxy);
+ }
+ }
+
+
+ /**
+ * Creates the client without the use of any proxy
+ */
+ public WineryRepositoryClient() {
+ this(false);
+ }
+
+ /**
+ * @param useProxy if a debugging proxy should be used
+ *
+ * @throws IllegalStateException if DOM parser could not be created
+ */
+ public WineryRepositoryClient(boolean useProxy) {
+ ClientConfig clientConfig = new DefaultClientConfig();
+ clientConfig.getClasses().add(JacksonJsonProvider.class);
+ if (useProxy) {
+ URLConnectionClientHandler ch = new URLConnectionClientHandler(new ConnectionFactory());
+ this.client = new Client(ch, clientConfig);
+ } else {
+ this.client = Client.create(clientConfig);
+ }
+
+ this.entityTypeDataCache = new HashMap<>();
+ this.nameCache = new HashMap<>();
+
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ if (WineryRepositoryClient.VALIDATING) {
+ factory.setValidating(true);
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ Schema schema;
+ URL resource = this.getClass().getResource("/TOSCA-v1.0.xsd");
+ try {
+ schema = schemaFactory.newSchema(resource);
+ } catch (SAXException e) {
+ throw new IllegalStateException("Schema could not be initalized", e);
+ }
+ factory.setSchema(schema);
+ }
+ try {
+ this.toscaDocumentBuilder = factory.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ throw new IllegalStateException("document builder could not be initalized", e);
+ }
+ /*
+ TODO: include this somehow - in the case of VALIDATING
+
+ Does not work with TTopolgoyTemplate as this is not allowed in the root of an XML document
+ this.toscaDocumentBuilder.setErrorHandler(new ErrorHandler() {
+
+ @Override
+ public void warning(SAXParseException arg0) throws SAXException {
+ throw arg0;
+ }
+
+ @Override
+ public void fatalError(SAXParseException arg0) throws SAXException {
+ throw arg0;
+ }
+
+ @Override
+ public void error(SAXParseException arg0) throws SAXException {
+ throw arg0;
+ }
+ });
+ */
+ }
+
+ private static JAXBContext initContext() {
+ // code copied+adapted from JAXBSupport
+
+ JAXBContext context;
+ try {
+ // For winery classes, eventually the package+jaxb.index method could be better. See http://stackoverflow.com/a/3628525/873282
+ // @formatter:off
+ context = JAXBContext.newInstance(
+ TDefinitions.class,
+ WinerysPropertiesDefinition.class);
+ // @formatter:on
+ } catch (JAXBException e) {
+ WineryRepositoryClient.logger.error("Could not initialize JAXBContext", e);
+ throw new IllegalStateException(e);
+ }
+ return context;
+ }
+
+ /**
+ * Creates a marshaller
+ *
+ * @throws IllegalStateException if marshaller could not be instantiated
+ */
+ private static Marshaller createMarshaller() {
+ // code copied+adapted from JAXBSupport
+ Marshaller m;
+ try {
+ m = WineryRepositoryClient.context.createMarshaller();
+ // pretty printed output is required as the XML is sent 1:1 to the browser for editing
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ // not possible here: m.setProperty("com.sun.xml.bind.namespacePrefixMapper", JAXBSupport.prefixMapper);
+ } catch (JAXBException e) {
+ WineryRepositoryClient.logger.error("Could not instantiate marshaller", e);
+ throw new IllegalStateException(e);
+ }
+ return m;
+ }
+
+ /**
+ * Creates a unmarshaller
+ *
+ * @throws IllegalStateException if unmarshaller could not be instantiated
+ */
+ private static Unmarshaller createUnmarshaller() {
+ Unmarshaller um;
+ try {
+ um = WineryRepositoryClient.context.createUnmarshaller();
+ } catch (JAXBException e) {
+ WineryRepositoryClient.logger.error("Could not instantiate unmarshaller", e);
+ throw new IllegalStateException(e);
+ }
+ return um;
+ }
+
+ /*** methods directly from IWineryRepositoryClient ***/
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addRepository(String uri) {
+ if (this.knownURIs.add(uri)) {
+ // URI is not already known, add a new resource
+ WebResource wr = this.client.resource(uri);
+ this.repositoryResources.add(wr);
+ if (this.primaryRepository == null) {
+ this.primaryRepository = uri;
+ this.primaryWebResource = wr;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getPrimaryRepository() {
+ return this.primaryRepository;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setPrimaryRepository(String uri) {
+ this.addRepository(uri);
+ // now we are sure that a web resource for the uri exists
+ this.primaryRepository = uri;
+ // Update the reference to the primaryWebResource
+ // The appropriate resource has been created via
+ // this.addRepository(uri);
+ for (WebResource wr : this.repositoryResources) {
+ if (wr.getURI().equals(uri)) {
+ this.primaryWebResource = wr;
+ break;
+ }
+ }
+ assert (this.primaryWebResource != null);
+ }
+
+ /*** methods directly from IWineryRepository ***/
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SortedSet<String> getNamespaces() {
+ SortedSet<String> res = new TreeSet<String>();
+ for (WebResource wr : this.repositoryResources) {
+ WebResource namespacesResource = wr.path("admin").path("namespaces");
+
+ // this could be parsed using JAXB
+ // (http://jersey.java.net/nonav/documentation/latest/json.html),
+ // but we are short in time, so we do a quick hack
+ String nsList = namespacesResource.accept(MediaType.APPLICATION_JSON).get(String.class);
+ WineryRepositoryClient.logger.trace(nsList);
+ List<String> nsListList;
+ try {
+ nsListList = this.mapper.readValue(nsList, new TypeReference<List<String>>() {
+ });
+ } catch (Exception e) {
+ WineryRepositoryClient.logger.error(e.getMessage(), e);
+ continue;
+ }
+ res.addAll(nsListList);
+ }
+ return res;
+ }
+
+ /**
+ * Base method for getQNameListOfAllTypes and getAllTypes.
+ */
+ private <T extends TExtensibleElements> Map<WebResource, List<NamespaceIdOptionalName>> getWRtoNamespaceAndIdListMapOfAllTypes(String path) {
+ Map<WebResource, List<NamespaceIdOptionalName>> res = new HashMap<WebResource, List<NamespaceIdOptionalName>>();
+ for (WebResource wr : this.repositoryResources) {
+ WebResource componentListResource = wr.path(path);
+
+ // this could be parsed using JAXB
+ // (http://jersey.java.net/nonav/documentation/latest/json.html),
+ // but we are short in time, so we do a quick hack
+ // The result also contains the optional name
+ String idList = componentListResource.accept(MediaType.APPLICATION_JSON).get(String.class);
+ WineryRepositoryClient.logger.trace(idList);
+ List<NamespaceIdOptionalName> nsAndIdList;
+ try {
+ nsAndIdList = this.mapper.readValue(idList, new TypeReference<List<NamespaceIdOptionalName>>() {
+ });
+ } catch (Exception e) {
+ WineryRepositoryClient.logger.error(e.getMessage(), e);
+ continue;
+ }
+ res.put(wr, nsAndIdList);
+ }
+ return res;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName(GenericId id) {
+ if (this.nameCache.containsKey(id)) {
+ return this.nameCache.get(id);
+ }
+
+ String name = null;
+ for (WebResource wr : this.repositoryResources) {
+ String pathFragment = IdUtil.getURLPathFragment(id);
+ WebResource resource = wr.path(pathFragment).path("name");
+ ClientResponse response = resource.accept(MediaType.TEXT_PLAIN_TYPE).get(ClientResponse.class);
+ if (response.getClientResponseStatus() == ClientResponse.Status.OK) {
+ name = response.getEntity(String.class);
+ // break loop as the first match is the final result
+ break;
+ }
+ }
+ // if all resources did not return "OK", "null" is returned
+
+ if (name != null) {
+ if (this.nameCache.size() > WineryRepositoryClient.MAX_NAME_CACHE_SIZE) {
+ // if cache grew too large, clear it.
+ this.nameCache.clear();
+ }
+ this.nameCache.put(id, name);
+ }
+
+ return name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <T extends TEntityType> List<QName> getQNameListOfAllTypes(Class<T> className) {
+ String path = Util.getURLpathFragmentForCollection(className);
+ Map<WebResource, List<NamespaceIdOptionalName>> wRtoNamespaceAndIdListMapOfAllTypes = this.getWRtoNamespaceAndIdListMapOfAllTypes(path);
+ Collection<List<NamespaceIdOptionalName>> namespaceAndIdListCollection = wRtoNamespaceAndIdListMapOfAllTypes.values();
+ List<QName> res = new ArrayList<QName>(namespaceAndIdListCollection.size());
+ for (List<NamespaceIdOptionalName> namespaceAndIdList : namespaceAndIdListCollection) {
+ for (NamespaceIdOptionalName namespaceAndId : namespaceAndIdList) {
+ QName qname = new QName(namespaceAndId.getNamespace(), namespaceAndId.getId());
+ res.add(qname);
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Fetches java objects at a given URL
+ *
+ * @param path the path to use. E.g., "nodetypes" for node types, ...
+ * @param className the class of the expected return type. May be
+ * TDefinitions or TEntityType. TDefinitions the mode is that the
+ * import statement are recursively resolved and added to the
+ * returned Defintitions elment
+ */
+ // we convert an object to T if it T is definitions
+ // does not work without compiler error
+ @SuppressWarnings("unchecked")
+ private <T extends TExtensibleElements> Collection<T> getAllTypes(String path, Class<T> className) {
+ Map<WebResource, List<NamespaceIdOptionalName>> wRtoNamespaceAndIdListMapOfAllTypes = this.getWRtoNamespaceAndIdListMapOfAllTypes(path);
+ // now we now all QNames. We have to fetch the full content now
+
+ Collection<T> res = new LinkedList<T>();
+ for (WebResource wr : wRtoNamespaceAndIdListMapOfAllTypes.keySet()) {
+ WebResource componentListResource = wr.path(path);
+
+ // go through all ids and fetch detailed information on each
+ // type
+
+ for (NamespaceIdOptionalName nsAndId : wRtoNamespaceAndIdListMapOfAllTypes.get(wr)) {
+ TDefinitions definitions = WineryRepositoryClient.getDefinitions(componentListResource, nsAndId.getNamespace(), nsAndId.getId());
+ if (definitions == null) {
+ // try next one
+ continue;
+ }
+
+ T result;
+
+ if (TDefinitions.class.equals(className)) {
+ // mode: complete definitions
+ result = (T) definitions;
+ } else {
+ // mode: only the nested element
+ // convention: first element in list is the element we look for
+ if (definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().isEmpty()) {
+ result = null;
+ WineryRepositoryClient.logger.error("Type {}/{} was found, but did not return any data", nsAndId.getNamespace(), nsAndId.getId());
+ } else {
+ WineryRepositoryClient.logger.trace("Probably found valid data for {}/{}", nsAndId.getNamespace(), nsAndId.getId());
+ result = (T) definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+
+ this.cache((TEntityType) result, new QName(nsAndId.getNamespace(), nsAndId.getId()));
+ }
+ }
+
+ // TODO: if multiple repositories are used, the new element
+ // should be put "sorted" into the list. This could be done by
+ // add(parsedResult, index), where index is calculated by
+ // incrementing index as long as the current element is smaller
+ // than the element to insert.
+ if (result != null) {
+ res.add(result);
+ }
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Caches the TEntityType data of a QName to avoid multiple get requests
+ *
+ * NOT thread safe
+ */
+ private void cache(TEntityType et, QName qName) {
+ Map<QName, TEntityType> map;
+ if ((map = this.entityTypeDataCache.get(et.getClass())) == null) {
+ map = new HashMap<>();
+ this.entityTypeDataCache.put(et.getClass(), map);
+ } else {
+ // quick hack to keep cache size small
+ if (map.size() > 1000) {
+ map.clear();
+ }
+ }
+ map.put(qName, et);
+ }
+
+ private static WebResource getTopologyTemplateWebResource(WebResource base, QName serviceTemplate) {
+ String nsEncoded = Util.DoubleURLencode(serviceTemplate.getNamespaceURI());
+ String idEncoded = Util.DoubleURLencode(serviceTemplate.getLocalPart());
+ WebResource res = base.path("servicetemplates").path(nsEncoded).path(idEncoded).path("topologytemplate");
+ return res;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Collection<QNameWithName> getListOfAllInstances(Class<? extends TOSCAComponentId> clazz) {
+ // inspired by getQNameListOfAllTypes
+ String path = Util.getRootPathFragment(clazz);
+ Map<WebResource, List<NamespaceIdOptionalName>> wRtoNamespaceAndIdListMapOfAllTypes = this.getWRtoNamespaceAndIdListMapOfAllTypes(path);
+ Collection<List<NamespaceIdOptionalName>> namespaceAndIdListCollection = wRtoNamespaceAndIdListMapOfAllTypes.values();
+ List<QNameWithName> res = new ArrayList<QNameWithName>(namespaceAndIdListCollection.size());
+
+ for (List<NamespaceIdOptionalName> namespaceAndIdList : namespaceAndIdListCollection) {
+ for (NamespaceIdOptionalName namespaceAndId : namespaceAndIdList) {
+ QNameWithName qn = new QNameWithName();
+ qn.qname = new QName(namespaceAndId.getNamespace(), namespaceAndId.getId());
+ qn.name = namespaceAndId.getName();
+ res.add(qn);
+ }
+ }
+ return res;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <T extends TEntityType> Collection<T> getAllTypes(Class<T> c) {
+ String urlPathFragment = Util.getURLpathFragmentForCollection(c);
+ Collection<T> allTypes = this.getAllTypes(urlPathFragment, c);
+ return allTypes;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T extends TEntityType> T getType(QName qname, Class<T> type) {
+ T res = null;
+ if (this.entityTypeDataCache.containsKey(type)) {
+ Map<QName, TEntityType> map = this.entityTypeDataCache.get(type);
+ if (map.containsKey(qname)) {
+ res = (T) map.get(qname);
+ }
+ }
+
+ if (res == null) {
+ // not yet seen, try to fetch resource
+
+ for (WebResource wr : this.repositoryResources) {
+ String path = Util.getURLpathFragmentForCollection(type);
+
+ TDefinitions definitions = WineryRepositoryClient.getDefinitions(wr, path, qname.getNamespaceURI(), qname.getLocalPart());
+
+ if (definitions == null) {
+ // in case of an error, just try the next one
+ continue;
+ }
+
+ res = (T) definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+ this.cache(res, qname);
+ break;
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * Tries to retrieve a TDefinitions from the given resource / encoded(ns) /
+ * encoded(localPart)
+ *
+ * @return null if 404 or other error
+ */
+ private static TDefinitions getDefinitions(WebResource wr, String path, String ns, String localPart) {
+ WebResource componentListResource = wr.path(path);
+ return WineryRepositoryClient.getDefinitions(componentListResource, ns, localPart);
+ }
+
+ /**
+ * Tries to retrieve a TDefinitions from the given resource / encoded(ns) /
+ * encoded(localPart)
+ *
+ * @return null if 404 or other error
+ */
+ private static TDefinitions getDefinitions(WebResource componentListResource, String ns, String localPart) {
+ // we need double encoding as the client decodes the URL once
+ String nsEncoded = Util.DoubleURLencode(ns);
+ String idEncoded = Util.DoubleURLencode(localPart);
+
+ WebResource instanceResource = componentListResource.path(nsEncoded).path(idEncoded);
+
+ // TODO: org.eclipse.winery.repository.resources.AbstractComponentInstanceResource.getDefinitionsWithAssociatedThings() could be used to do the resolving at the server
+
+ ClientResponse response = instanceResource.accept(MimeTypes.MIMETYPE_TOSCA_DEFINITIONS).get(ClientResponse.class);
+ if (response.getStatus() != 200) {
+ // also handles 404
+ return null;
+ }
+
+ TDefinitions definitions;
+ try {
+ Unmarshaller um = WineryRepositoryClient.createUnmarshaller();
+ definitions = (TDefinitions) um.unmarshal(response.getEntityInputStream());
+ } catch (JAXBException e) {
+ WineryRepositoryClient.logger.error("Could not umarshal TDefinitions", e);
+ // try next service
+ return null;
+ }
+ return definitions;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <T extends TEntityType> Collection<TDefinitions> getAllTypesWithAssociatedElements(Class<T> c) {
+ String urlPathFragment = Util.getURLpathFragmentForCollection(c);
+ Collection<TDefinitions> allTypes = this.getAllTypes(urlPathFragment, TDefinitions.class);
+ return allTypes;
+ }
+
+ /**
+ *
+ * @param stream the stream to parse
+ * @return null if document is invalid
+ */
+ private Document parseAndValidateTOSCAXML(InputStream stream) {
+ Document document;
+ try {
+ document = this.toscaDocumentBuilder.parse(stream);
+ } catch (SAXException | IOException e) {
+ WineryRepositoryClient.logger.debug("Could not parse TOSCA file", e);
+ return null;
+ }
+ return document;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public TTopologyTemplate getTopologyTemplate(QName serviceTemplate) {
+ // we try all repositories until the first hit
+ for (WebResource wr : this.repositoryResources) {
+ WebResource r = WineryRepositoryClient.getTopologyTemplateWebResource(wr, serviceTemplate);
+ ClientResponse response = r.accept(MediaType.TEXT_XML).get(ClientResponse.class);
+ if (response.getClientResponseStatus() == ClientResponse.Status.OK) {
+ TTopologyTemplate topologyTemplate;
+ Document doc = this.parseAndValidateTOSCAXML(response.getEntityInputStream());
+ if (doc == null) {
+ // no valid document
+ return null;
+ }
+ try {
+ topologyTemplate = WineryRepositoryClient.createUnmarshaller().unmarshal(doc.getDocumentElement(), TTopologyTemplate.class).getValue();
+ } catch (JAXBException e) {
+ WineryRepositoryClient.logger.debug("Could not parse topology, returning null", e);
+ return null;
+ }
+ // first hit: immediately stop and return result
+ return topologyTemplate;
+ }
+ }
+ // nothing found
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setTopologyTemplate(QName serviceTemplate, TTopologyTemplate topologyTemplate) throws Exception {
+ WebResource r = WineryRepositoryClient.getTopologyTemplateWebResource(this.primaryWebResource, serviceTemplate);
+ String xmlAsString = Util.getXMLAsString(TTopologyTemplate.class, topologyTemplate);
+ ClientResponse response = r.type(MediaType.TEXT_XML).put(ClientResponse.class, xmlAsString);
+ WineryRepositoryClient.logger.debug(response.toString());
+ int status = response.getStatus();
+ if ((status < 200) || (status >= 300)) {
+ throw new Exception(response.toString());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public QName getArtifactTypeQNameForExtension(String extension) {
+ // we try all repositories until the first hit
+ for (WebResource wr : this.repositoryResources) {
+ WebResource artifactTypesResource = wr.path("artifacttypes").queryParam("extension", extension);
+ ClientResponse response = artifactTypesResource.accept(MediaType.TEXT_PLAIN).get(ClientResponse.class);
+ if (response.getClientResponseStatus() == ClientResponse.Status.OK) {
+ QName res = QName.valueOf(response.getEntity(String.class));
+ return res;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Does NOT check for global QName uniqueness, only in the scope of all
+ * artifact templates
+ */
+ @Override
+ public void createArtifactTemplate(QName qname, QName artifactType) throws QNameAlreadyExistsException {
+ WebResource artifactTemplates = this.primaryWebResource.path("artifacttemplates");
+ MultivaluedMap<String, String> map = new MultivaluedMapImpl();
+ map.putSingle("namespace", qname.getNamespaceURI());
+ map.putSingle("name", qname.getLocalPart());
+ map.putSingle("type", artifactType.toString());
+ ClientResponse response = artifactTemplates.type(MediaType.APPLICATION_FORM_URLENCODED).accept(MediaType.TEXT_PLAIN).post(ClientResponse.class, map);
+ if (response.getClientResponseStatus() != ClientResponse.Status.CREATED) {
+ // TODO: pass ClientResponse.Status somehow
+ // TODO: more fine grained checking for error message. Not all
+ // failures are that the QName already exists
+ WineryRepositoryClient.logger.debug(String.format("Error %d when creating id %s from URI %s", response.getStatus(), qname.toString(), this.primaryWebResource.getURI().toString()));
+ throw new QNameAlreadyExistsException();
+ }
+ // no further return is made
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void createComponent(QName qname, Class<? extends TOSCAComponentId> idClass) throws QNameAlreadyExistsException {
+ WebResource resource = this.primaryWebResource.path(Util.getRootPathFragment(idClass));
+ MultivaluedMap<String, String> map = new MultivaluedMapImpl();
+ map.putSingle("namespace", qname.getNamespaceURI());
+ map.putSingle("name", qname.getLocalPart());
+ ClientResponse response = resource.type(MediaType.APPLICATION_FORM_URLENCODED).accept(MediaType.TEXT_PLAIN).post(ClientResponse.class, map);
+ if (response.getClientResponseStatus() != ClientResponse.Status.CREATED) {
+ // TODO: pass ClientResponse.Status somehow
+ // TODO: more fine grained checking for error message. Not all failures are that the QName already exists
+ WineryRepositoryClient.logger.debug(String.format("Error %d when creating id %s from URI %s", response.getStatus(), qname.toString(), this.primaryWebResource.getURI().toString()));
+ throw new QNameAlreadyExistsException();
+ }
+ // no further return is made
+ }
+
+ @Override
+ public void forceDelete(GenericId id) throws IOException {
+ String pathFragment = IdUtil.getURLPathFragment(id);
+ for (WebResource wr : this.repositoryResources) {
+ ClientResponse response = wr.path(pathFragment).delete(ClientResponse.class);
+ if ((response.getClientResponseStatus() != ClientResponse.Status.NO_CONTENT) || (response.getClientResponseStatus() != ClientResponse.Status.NOT_FOUND)) {
+ WineryRepositoryClient.logger.debug(String.format("Error %d when deleting id %s from URI %s", response.getStatus(), id.toString(), wr.getURI().toString()));
+ }
+ }
+ }
+
+ @Override
+ public boolean primaryRepositoryAvailable() {
+ if (this.primaryWebResource == null) {
+ return false;
+ }
+
+ ClientResponse response = this.primaryWebResource.get(ClientResponse.class);
+ boolean res = (response.getClientResponseStatus() == ClientResponse.Status.OK);
+ return res;
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/WineryRepositoryClientFactory.java b/winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/WineryRepositoryClientFactory.java
new file mode 100644
index 0000000..59f0166
--- /dev/null
+++ b/winery/org.eclipse.winery.repository.client/src/main/java/org/eclipse/winery/repository/client/WineryRepositoryClientFactory.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 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
+ *******************************************************************************/
+package org.eclipse.winery.repository.client;
+
+public class WineryRepositoryClientFactory {
+
+ public static IWineryRepositoryClient getWineryRepositoryClient() {
+ return new WineryRepositoryClient();
+ }
+
+}
diff --git a/winery/org.eclipse.winery.repository.client/src/main/resources/TOSCA-v1.0.xsd b/winery/org.eclipse.winery.repository.client/src/main/resources/TOSCA-v1.0.xsd
new file mode 100644
index 0000000..8bed0e0
--- /dev/null
+++ b/winery/org.eclipse.winery.repository.client/src/main/resources/TOSCA-v1.0.xsd
@@ -0,0 +1,791 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Topology and Orchestration Specification for Cloud Applications Version 1.0
+ Committee Specification Draft 08
+ 09 May 2013
+ Copyright (c) OASIS Open 2013. All rights reserved.
+ Source: http://docs.oasis-open.org/tosca/TOSCA/v1.0/csd08/schemas/
+-->
+<xs:schema targetNamespace="http://docs.oasis-open.org/tosca/ns/2011/12" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns="http://docs.oasis-open.org/tosca/ns/2011/12" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ <xs:element name="documentation" type="tDocumentation"/>
+ <xs:complexType name="tDocumentation" mixed="true">
+ <xs:sequence>
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="source" type="xs:anyURI"/>
+ <xs:attribute ref="xml:lang"/>
+ </xs:complexType>
+ <xs:complexType name="tExtensibleElements">
+ <xs:sequence>
+ <xs:element ref="documentation" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:complexType name="tImport">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="namespace" type="xs:anyURI"/>
+ <xs:attribute name="location" type="xs:anyURI"/>
+ <xs:attribute name="importType" type="importedURI" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="Definitions">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="tDefinitions"/>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="tDefinitions">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Extensions" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Extension" type="tExtension" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Import" type="tImport" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="Types" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="ServiceTemplate" type="tServiceTemplate"/>
+ <xs:element name="NodeType" type="tNodeType"/>
+ <xs:element name="NodeTypeImplementation" type="tNodeTypeImplementation"/>
+ <xs:element name="RelationshipType" type="tRelationshipType"/>
+ <xs:element name="RelationshipTypeImplementation" type="tRelationshipTypeImplementation"/>
+ <xs:element name="RequirementType" type="tRequirementType"/>
+ <xs:element name="CapabilityType" type="tCapabilityType"/>
+ <xs:element name="ArtifactType" type="tArtifactType"/>
+ <xs:element name="ArtifactTemplate" type="tArtifactTemplate"/>
+ <xs:element name="PolicyType" type="tPolicyType"/>
+ <xs:element name="PolicyTemplate" type="tPolicyTemplate"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tServiceTemplate">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Tags" type="tTags" minOccurs="0"/>
+ <xs:element name="BoundaryDefinitions" type="tBoundaryDefinitions" minOccurs="0"/>
+ <xs:element name="TopologyTemplate" type="tTopologyTemplate"/>
+ <xs:element name="Plans" type="tPlans" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI"/>
+ <xs:attribute name="substitutableNodeType" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tTags">
+ <xs:sequence>
+ <xs:element name="Tag" type="tTag" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tTag">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tBoundaryDefinitions">
+ <xs:sequence>
+ <xs:element name="Properties" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other"/>
+ <xs:element name="PropertyMappings" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PropertyMapping" type="tPropertyMapping" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PropertyConstraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PropertyConstraint" type="tPropertyConstraint" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Requirements" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Requirement" type="tRequirementRef" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Capabilities" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Capability" type="tCapabilityRef" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Policies" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Policy" type="tPolicy" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Interfaces" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Interface" type="tExportedInterface" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tPropertyMapping">
+ <xs:attribute name="serviceTemplatePropertyRef" type="xs:string" use="required"/>
+ <xs:attribute name="targetObjectRef" type="xs:IDREF" use="required"/>
+ <xs:attribute name="targetPropertyRef" type="xs:string" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tRequirementRef">
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tCapabilityRef">
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tEntityType" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Tags" type="tTags" minOccurs="0"/>
+ <xs:element name="DerivedFrom" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PropertiesDefinition" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="element" type="xs:QName"/>
+ <xs:attribute name="type" type="xs:QName"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ <xs:attribute name="abstract" type="tBoolean" default="no"/>
+ <xs:attribute name="final" type="tBoolean" default="no"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tEntityTemplate" abstract="true">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Properties" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PropertyConstraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="PropertyConstraint" type="tPropertyConstraint" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID" use="required"/>
+ <xs:attribute name="type" type="xs:QName" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tNodeTemplate">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:sequence>
+ <xs:element name="Requirements" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Requirement" type="tRequirement" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Capabilities" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Capability" type="tCapability" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Policies" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Policy" type="tPolicy" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="DeploymentArtifacts" type="tDeploymentArtifacts" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="minInstances" type="xs:int" use="optional" default="1"/>
+ <xs:attribute name="maxInstances" use="optional" default="1">
+ <xs:simpleType>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:pattern value="([1-9]+[0-9]*)"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="unbounded"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tTopologyTemplate">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="NodeTemplate" type="tNodeTemplate"/>
+ <xs:element name="RelationshipTemplate" type="tRelationshipTemplate"/>
+ </xs:choice>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRelationshipType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType">
+ <xs:sequence>
+ <xs:element name="InstanceStates" type="tTopologyElementInstanceStates" minOccurs="0"/>
+ <xs:element name="SourceInterfaces" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Interface" type="tInterface" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TargetInterfaces" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Interface" type="tInterface" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidSource" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ValidTarget" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRelationshipTypeImplementation">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Tags" type="tTags" minOccurs="0"/>
+ <xs:element name="DerivedFrom" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="relationshipTypeImplementationRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RequiredContainerFeatures" type="tRequiredContainerFeatures" minOccurs="0"/>
+ <xs:element name="ImplementationArtifacts" type="tImplementationArtifacts" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+ <xs:attribute name="relationshipType" type="xs:QName" use="required"/>
+ <xs:attribute name="abstract" type="tBoolean" use="optional" default="no"/>
+ <xs:attribute name="final" type="tBoolean" use="optional" default="no"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRelationshipTemplate">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:sequence>
+ <xs:element name="SourceElement">
+ <xs:complexType>
+ <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TargetElement">
+ <xs:complexType>
+ <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RelationshipConstraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="RelationshipConstraint" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="constraintType" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tNodeType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType">
+ <xs:sequence>
+ <xs:element name="RequirementDefinitions" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="RequirementDefinition" type="tRequirementDefinition" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="CapabilityDefinitions" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="CapabilityDefinition" type="tCapabilityDefinition" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="InstanceStates" type="tTopologyElementInstanceStates" minOccurs="0"/>
+ <xs:element name="Interfaces" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Interface" type="tInterface" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tNodeTypeImplementation">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Tags" type="tTags" minOccurs="0"/>
+ <xs:element name="DerivedFrom" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="nodeTypeImplementationRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RequiredContainerFeatures" type="tRequiredContainerFeatures" minOccurs="0"/>
+ <xs:element name="ImplementationArtifacts" type="tImplementationArtifacts" minOccurs="0"/>
+ <xs:element name="DeploymentArtifacts" type="tDeploymentArtifacts" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+ <xs:attribute name="nodeType" type="xs:QName" use="required"/>
+ <xs:attribute name="abstract" type="tBoolean" use="optional" default="no"/>
+ <xs:attribute name="final" type="tBoolean" use="optional" default="no"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRequirementType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType">
+ <xs:attribute name="requiredCapabilityType" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRequirementDefinition">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Constraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Constraint" type="tConstraint" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="requirementType" type="xs:QName" use="required"/>
+ <xs:attribute name="lowerBound" type="xs:int" use="optional" default="1"/>
+ <xs:attribute name="upperBound" use="optional" default="1">
+ <xs:simpleType>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:pattern value="([1-9]+[0-9]*)"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="unbounded"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRequirement">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tCapabilityType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType"/>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tCapabilityDefinition">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Constraints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Constraint" type="tConstraint" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="capabilityType" type="xs:QName" use="required"/>
+ <xs:attribute name="lowerBound" type="xs:int" use="optional" default="1"/>
+ <xs:attribute name="upperBound" use="optional" default="1">
+ <xs:simpleType>
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="xs:nonNegativeInteger">
+ <xs:pattern value="([1-9]+[0-9]*)"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="unbounded"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tCapability">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tArtifactType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType"/>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tArtifactTemplate">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:sequence>
+ <xs:element name="ArtifactReferences" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ArtifactReference" type="tArtifactReference" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tDeploymentArtifacts">
+ <xs:sequence>
+ <xs:element name="DeploymentArtifact" type="tDeploymentArtifact" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tDeploymentArtifact">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="artifactType" type="xs:QName" use="required"/>
+ <xs:attribute name="artifactRef" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tImplementationArtifacts">
+ <xs:sequence>
+ <xs:element name="ImplementationArtifact" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="tImplementationArtifact"/>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tImplementationArtifact">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="interfaceName" type="xs:anyURI" use="optional"/>
+ <xs:attribute name="operationName" type="xs:NCName" use="optional"/>
+ <xs:attribute name="artifactType" type="xs:QName" use="required"/>
+ <xs:attribute name="artifactRef" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tPlans">
+ <xs:sequence>
+ <xs:element name="Plan" type="tPlan" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+ </xs:complexType>
+ <xs:complexType name="tPlan">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Precondition" type="tCondition" minOccurs="0"/>
+ <xs:element name="InputParameters" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="InputParameter" type="tParameter" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="OutputParameters" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="OutputParameter" type="tParameter" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:choice>
+ <xs:element name="PlanModel">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PlanModelReference">
+ <xs:complexType>
+ <xs:attribute name="reference" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:ID" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="planType" type="xs:anyURI" use="required"/>
+ <xs:attribute name="planLanguage" type="xs:anyURI" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tPolicyType">
+ <xs:complexContent>
+ <xs:extension base="tEntityType">
+ <xs:sequence>
+ <xs:element name="AppliesTo" type="tAppliesTo" minOccurs="0"/>
+ </xs:sequence>
+ <xs:attribute name="policyLanguage" type="xs:anyURI" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tPolicyTemplate">
+ <xs:complexContent>
+ <xs:extension base="tEntityTemplate">
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tAppliesTo">
+ <xs:sequence>
+ <xs:element name="NodeTypeReference" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tPolicy">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ <xs:attribute name="policyType" type="xs:QName" use="required"/>
+ <xs:attribute name="policyRef" type="xs:QName" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tConstraint">
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="constraintType" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tPropertyConstraint">
+ <xs:complexContent>
+ <xs:extension base="tConstraint">
+ <xs:attribute name="property" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tExtensions">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="Extension" type="tExtension" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tExtension">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:attribute name="namespace" type="xs:anyURI" use="required"/>
+ <xs:attribute name="mustUnderstand" type="tBoolean" use="optional" default="yes"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tParameter">
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="type" type="xs:string" use="required"/>
+ <xs:attribute name="required" type="tBoolean" use="optional" default="yes"/>
+ </xs:complexType>
+ <xs:complexType name="tInterface">
+ <xs:sequence>
+ <xs:element name="Operation" type="tOperation" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tExportedInterface">
+ <xs:sequence>
+ <xs:element name="Operation" type="tExportedOperation" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tOperation">
+ <xs:complexContent>
+ <xs:extension base="tExtensibleElements">
+ <xs:sequence>
+ <xs:element name="InputParameters" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="InputParameter" type="tParameter" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="OutputParameters" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="OutputParameter" type="tParameter" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tExportedOperation">
+ <xs:choice>
+ <xs:element name="NodeOperation">
+ <xs:complexType>
+ <xs:attribute name="nodeRef" type="xs:IDREF" use="required"/>
+ <xs:attribute name="interfaceName" type="xs:anyURI" use="required"/>
+ <xs:attribute name="operationName" type="xs:NCName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RelationshipOperation">
+ <xs:complexType>
+ <xs:attribute name="relationshipRef" type="xs:IDREF" use="required"/>
+ <xs:attribute name="interfaceName" type="xs:anyURI" use="required"/>
+ <xs:attribute name="operationName" type="xs:NCName" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Plan">
+ <xs:complexType>
+ <xs:attribute name="planRef" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:NCName" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tCondition">
+ <xs:sequence>
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="expressionLanguage" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tTopologyElementInstanceStates">
+ <xs:sequence>
+ <xs:element name="InstanceState" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="state" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tArtifactReference">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="Include">
+ <xs:complexType>
+ <xs:attribute name="pattern" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Exclude">
+ <xs:complexType>
+ <xs:attribute name="pattern" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="reference" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tRequiredContainerFeatures">
+ <xs:sequence>
+ <xs:element name="RequiredContainerFeature" type="tRequiredContainerFeature" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tRequiredContainerFeature">
+ <xs:attribute name="feature" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:simpleType name="tBoolean">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="importedURI">
+ <xs:restriction base="xs:anyURI"/>
+ </xs:simpleType>
+</xs:schema>
diff --git a/winery/org.eclipse.winery.repository.client/src/test/java/META-INF/MANIFEST.MF b/winery/org.eclipse.winery.repository.client/src/test/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..254272e
--- /dev/null
+++ b/winery/org.eclipse.winery.repository.client/src/test/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
diff --git a/winery/org.eclipse.winery.repository.client/src/test/java/org/eclipse/winery/repository/client/TestWineryRepositoryClient.java b/winery/org.eclipse.winery.repository.client/src/test/java/org/eclipse/winery/repository/client/TestWineryRepositoryClient.java
new file mode 100644
index 0000000..77ab588
--- /dev/null
+++ b/winery/org.eclipse.winery.repository.client/src/test/java/org/eclipse/winery/repository/client/TestWineryRepositoryClient.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2013 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
+ *******************************************************************************/
+package org.eclipse.winery.repository.client;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.eclipse.winery.model.tosca.TDefinitions;
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeType;
+import org.eclipse.winery.model.tosca.TRelationshipType;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId;
+import org.eclipse.winery.common.interfaces.QNameAlreadyExistsException;
+
+/**
+ * Tests client methods with a pre-configured client stored in a local static
+ * field.
+ *
+ * Client creation and multiple repositories are not tested. This should be
+ * subject to other test classes.
+ *
+ * TODO: This class expects things to be existent in the namespace "test". This
+ * should be enforced in a preload.
+ */
+@RunWith(JUnit4.class)
+public class TestWineryRepositoryClient {
+
+ // private final String repositoryURI = "http://2471.de:8080/wineydev";
+ private static final String repositoryURI = "http://localhost:8080/winery";
+
+ private static final boolean USE_PROXY = true;
+
+ private static final IWineryRepositoryClient client = new WineryRepositoryClient(TestWineryRepositoryClient.USE_PROXY);
+ static {
+ TestWineryRepositoryClient.client.addRepository(TestWineryRepositoryClient.repositoryURI);
+ }
+
+ /**
+ * The namespace to put new things in. <br />
+ * TODO: Is deleted completely after testing
+ */
+ private static final String namespaceForNewArtifacts = "http://www.example.org/test/wineryclient/";
+
+
+ @Test
+ public void getAllNodeTypes() {
+ Collection<TNodeType> allTypes = TestWineryRepositoryClient.client.getAllTypes(TNodeType.class);
+ for (TNodeType type : allTypes) {
+ Assert.assertNotNull("name is null", type.getName());
+ Assert.assertNotNull("target namespace is null", type.getTargetNamespace());
+ }
+ }
+
+ @Test
+ public void getAllRelationshipTypes() {
+ Collection<TRelationshipType> allTypes = TestWineryRepositoryClient.client.getAllTypes(TRelationshipType.class);
+ for (TRelationshipType type : allTypes) {
+ Assert.assertNotNull("name is null", type.getName());
+ Assert.assertNotNull("target namespace is null", type.getTargetNamespace());
+ }
+ }
+
+ @Test
+ public void getAllNodeTypesWithAssociatedElements() {
+ Collection<TDefinitions> allTypes = TestWineryRepositoryClient.client.getAllTypesWithAssociatedElements(TNodeType.class);
+ Assert.assertNotNull(allTypes);
+ }
+
+ @Test
+ public void getAllRelationshipTypesWithAssociatedElements() {
+ Collection<TDefinitions> allTypes = TestWineryRepositoryClient.client.getAllTypesWithAssociatedElements(TRelationshipType.class);
+ Assert.assertNotNull(allTypes);
+ }
+
+ @Test
+ public void getPropertiesOfAllNodeTypes() {
+ // TODO
+ }
+
+ @Test
+ public void getPropertiesOfAllRelationshipTypes() {
+ // TODO
+ }
+
+ @Test
+ public void getTestTopologyTemplate() {
+ QName serviceTemplate = new QName("test", "test");
+ TTopologyTemplate topologyTemplate = TestWineryRepositoryClient.client.getTopologyTemplate(serviceTemplate);
+ Assert.assertNotNull(topologyTemplate);
+ }
+
+ @Test
+ public void getPropertiesOfTestTopologyTemplate() {
+ QName serviceTemplate = new QName("test", "test");
+ TTopologyTemplate topologyTemplate = TestWineryRepositoryClient.client.getTopologyTemplate(serviceTemplate);
+ Assert.assertNotNull(topologyTemplate);
+ List<TEntityTemplate> allTemplates = topologyTemplate.getNodeTemplateOrRelationshipTemplate();
+ for (TEntityTemplate e : allTemplates) {
+ // TODO
+ }
+ }
+
+ @Test
+ public void artifactTypeForWARfiles() {
+ QName artifactType = TestWineryRepositoryClient.client.getArtifactTypeQNameForExtension("war");
+ Assert.assertNotNull("Artifact Type for .war does not exist", artifactType);
+ }
+
+ @Test
+ public void createArtifactTemplate() throws IOException, QNameAlreadyExistsException {
+ // assure that the artifact type exists
+ QName artifactTypeQName = TestWineryRepositoryClient.client.getArtifactTypeQNameForExtension("war");
+ Assert.assertNotNull("Artifact Type for .war does not exist", artifactTypeQName);
+
+ // assure that the artifact template does not yet exist
+ // one possibility is to delete the artifact template, the other
+ // possibility is to
+
+ QName artifactTemplateQName = new QName(TestWineryRepositoryClient.namespaceForNewArtifacts, "artifactTemplate");
+ ArtifactTemplateId atId = new ArtifactTemplateId(artifactTemplateQName);
+
+ // ensure that the template does not exist yet
+ TestWineryRepositoryClient.client.forceDelete(atId);
+
+ TestWineryRepositoryClient.client.createArtifactTemplate(artifactTemplateQName, artifactTypeQName);
+ }
+}