diff --git a/README.md b/README.md
index e824971e9..639988af8 100644
--- a/README.md
+++ b/README.md
@@ -10,15 +10,31 @@ Build: [](htt
* You can also check out our [Project Homepage](https://projects.eclipse.org/projects/iot.hawkbit) for further contact options.
-# Compile
-```
-mvn install
-```
-
-# Run and use
+# Compile, Run and Getting Started
We are not providing an off the shelf installation ready hawkBit update server. However, we recommend to check out the [Example Application](examples/hawkbit-example-app) for a runtime ready Spring Boot based update server that is empowered by hawkBit.
+#### Clone and build hawkBit
+```
+$ git clone https://github.com/eclipse/hawkbit.git
+$ mvn clean install
+```
+#### Start hawkBit example app
+[Example Application](examples/hawkbit-example-app)
+```
+$ java –jar ./examples/hawkbit-example-app/target/hawkbit-example-app-#version#.jar
+```
+#### Start hawkBit device simulator
+[Device Simulator](examples/hawkbit-device-simulator)
+```
+$ java –jar ./examples/hawkbit-device-simulator/target/hawkbit-device-simulator-#version#.jar
+```
+#### Generate Getting Started data
+[Example Management API Client](examples/hawkbit-mgmt-api-client)
+```
+$ java –jar ./examples/hawkbit-mgmt-api-client/target/hawkbit-mgmt-api-client-#version#.jar
+```
+
# Releases and Roadmap
* We are currently working on the first formal release under the Eclipse banner: 0.1 (see [Release 0.1 branch](https://github.com/eclipse/hawkbit/tree/release-train-0.1)).
@@ -29,11 +45,10 @@ We are not providing an off the shelf installation ready hawkBit update server.
* And of course tons of usability improvements and bug fixes.
-## Try out examples
-#### Standalone Test Application Server
-[Example Application](examples/hawkbit-example-app)
-#### Device Simulator using the DMF AMQP API
-[Device Simulator](examples/hawkbit-device-simulator)
+# Device Integration
+There are two device integration APIs provided by the hawkbit update server.
+* [Direct Device Integration API (HTTP)](DDIA.md)
+* [Device Management Federation API (AMQP)](DMFA.md)
# Modules
`hawkbit-core` : core elements.
@@ -49,9 +64,3 @@ We are not providing an off the shelf installation ready hawkBit update server.
`hawkbit-rest-resource` : HTTP REST endpoints for the Management and the Direct Device API.
`hawkbit-ui` : Vaadin UI.
`hawkbit-cache-redis` : spring cache manager configuration and implementation with redis, distributed cache and distributed events.
-
-
-# Device Integration
-There are two device integration APIs provided by the hawkbit update server.
-* [Direct Device Integration API (HTTP)](DDIA.md)
-* [Device Management Federation API (AMQP)](DMFA.md)
diff --git a/examples/hawkbit-mgmt-api-client/README.md b/examples/hawkbit-mgmt-api-client/README.md
index 7eb32f9e6..eff301e20 100644
--- a/examples/hawkbit-mgmt-api-client/README.md
+++ b/examples/hawkbit-mgmt-api-client/README.md
@@ -1,3 +1,39 @@
+# HawkBit management API example
+
Example client that shows how to efficiently use the hawkBit management API.
-Powered by [Feign](https://github.com/Netflix/feign).
\ No newline at end of file
+Powered by [Feign](https://github.com/Netflix/feign).
+
+## How to run the example client
+
+Run getting started example
+
+
+
+ $ java -jar hawkbit-mgmt-api-client-#version#.jar
+
+
+Run create and start rollout example
+
+
+ $ java -jar hawkbit-mgmt-api-client-#version#.jar --createrollout
+
+
+## This example shows
+
+In getting started example:
+* creating software modules type
+* creating distribution set type
+* creating distribution sets
+* creating software modules
+* assigning software modules to distribution sets
+
+In rollout mode:
+* creating software modules type
+* creating distribution set type
+* creating distribution sets
+* creating software modules
+* assigning software modules to distribution sets
+* creating a rollout
+* starting a rollout
+
diff --git a/examples/hawkbit-mgmt-api-client/pom.xml b/examples/hawkbit-mgmt-api-client/pom.xml
index cced3dfbb..df55dc6ae 100644
--- a/examples/hawkbit-mgmt-api-client/pom.xml
+++ b/examples/hawkbit-mgmt-api-client/pom.xml
@@ -1,13 +1,6 @@
-
+
4.0.0
@@ -16,9 +9,43 @@
hawkbit-examples-parent
0.2.0-SNAPSHOT
+ jar
hawkbit-mgmt-api-client
hawkBit Management API example client
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+ ${baseDir}
+ false
+ org.eclipse.hawkbit.mgmt.client.Application
+ JAR
+
+
+
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-netflix
+ 1.0.7.RELEASE
+ pom
+ import
+
+
+
@@ -26,45 +53,32 @@
hawkbit-rest-api
${project.version}
-
- com.netflix.feign
- feign-jackson
- 8.12.1
-
com.netflix.feign
feign-core
- 8.12.1
+
+ 8.14.2
-
-
- org.eclipse.hawkbit
- hawkbit-example-app
- ${project.version}
- test
+ hibernate-validator
+ org.hibernate
org.springframework.boot
- spring-boot-starter-test
- test
+ spring-boot-starter
- ru.yandex.qatools.allure
- allure-junit-adaptor
- test
+ org.springframework.cloud
+ spring-cloud-starter-feign
- org.easytesting
- fest-assert-core
- test
+ org.springframework.boot
+ spring-boot-starter-logging
- org.easytesting
- fest-assert
- test
+ com.google.collections
+ google-collections
+ 1.0-rc2
-
-
\ No newline at end of file
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetResource.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetResource.java
deleted file mode 100644
index 62c987ae8..000000000
--- a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetResource.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.mgmt.api.client;
-
-import java.util.List;
-
-import org.eclipse.hawkbit.rest.resource.RestConstants;
-import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRequestBodyPost;
-import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
-
-import feign.Headers;
-import feign.RequestLine;
-
-/**
- * Client binding for the Distribution resource of the management API.
- */
-@FunctionalInterface
-public interface DistributionSetResource {
-
- /**
- * Creates a list of distribution sets.
- *
- * @param sets
- * the request body java bean containing the necessary attributes
- * for creating a distribution set.
- * @return the list of targets which have been created
- */
- @RequestLine("POST " + RestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
- @Headers("Content-Type: application/json")
- DistributionSetsRest createDistributionSets(final List sets);
-
-}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistrubutionSetTagResource.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistrubutionSetTagResource.java
deleted file mode 100644
index fe7a147a8..000000000
--- a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/DistrubutionSetTagResource.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.mgmt.api.client;
-
-import java.util.List;
-
-import org.eclipse.hawkbit.rest.resource.RestConstants;
-import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.AssignedDistributionSetRequestBody;
-import org.eclipse.hawkbit.rest.resource.model.tag.DistributionSetTagAssigmentResultRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
-
-import feign.Headers;
-import feign.Param;
-import feign.RequestLine;
-
-/**
- * Client binding for the DistributionSetTag resource of the management API.
- */
-public interface DistrubutionSetTagResource {
-
- /**
- * Retrieves a single distributionset tag based on the given ID.
- *
- * @param dsTagId
- * the ID of the distributionset tag to retrieve
- * @return a deserialized java bean containing the attributes of the
- * returned distributionset tag
- */
- @RequestLine("GET " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + "/{dsTagId}")
- TagRest getDistributionSetTag(@Param("dsTagId") Long dsTagId);
-
- /**
- * Creates a list of distributionset tags.
- *
- * @param tags
- * the tags to be created
- * @return the created tag list
- */
- @RequestLine("POST " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING)
- @Headers("Content-Type: application/json")
- TagsRest createDistributionSetTags(List tags);
-
- /**
- * Update attributes of a distributionset tag.
- *
- * @param dsTagId
- * the distributionset tag id to be updated
- * @param tag
- * the request body
- * @return the updated distributionset tag
- */
- @RequestLine("PUT " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + "/{dsTagId}")
- @Headers("Content-Type: application/json")
- TagRest updateDistributionSetTag(@Param("dsTagId") Long dsTagId, TagRequestBodyPut tag);
-
- /**
- * Deletes given distributionset tag on given ID.
- *
- * @param dsTagId
- * to be deleted
- */
- @RequestLine("DELETE " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING + "/{dsTagId}")
- void deleteDistributionSetTag(@Param("dsTagId") final Long dsTagId);
-
- /**
- * Retrieves a all assigned targets on the given distributionset tag id.
- *
- * @param dsTagId
- * the ID of the distributionset tag to retrieve
- * @return a list of targets
- */
- @RequestLine("GET " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
- + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
- DistributionSetsRest getAssignedDistributionSets(@Param("dsTagId") final Long dsTagId);
-
- /**
- * Toggle the tag assignment all assigned targets will be unassigned and all
- * unassigned targets will be assigned.
- *
- * @param dsTagId
- * the ID of the distributionset tag to toggle
- * @param assignedTargetRequestBodies
- * a list of controller ids
- * @return a list of assigned and unassigned targets
- */
- @RequestLine("POST " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
- + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING + "/toggleTagAssignment")
- @Headers("Content-Type: application/json")
- DistributionSetTagAssigmentResultRest toggleTagAssignment(@Param("dsTagId") final Long dsTagId,
- final List assignedTargetRequestBodies);
-
- /**
- * Assign targets to a given distributionset tag id.
- *
- * @param dsTagId
- * the ID of the distributionset tag to add the targets
- * @param assignedTargetRequestBodies
- * a list of controller ids
- * @return a list of assigned targets
- */
- @RequestLine("POST " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
- + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
- @Headers("Content-Type: application/json")
- TargetsRest assignDistributionSets(@Param("dsTagId") final Long dsTagId,
- final List assignedTargetRequestBodies);
-
- /**
- * Unassign targets to a given distributionset tag id.
- *
- * @param dsTagId
- * the ID of the distributionset tag to add the targets
- */
- @RequestLine("DELETE " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
- + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
- void unassignDistributionSets(@Param("dsTagId") final Long dsTagId);
-
- /**
- * Unassign one target to a given distributionset tag id.
- *
- * @param dsTagId
- * the ID of the distributionset tag to add the targets param
- * @param dsId
- * the distributionset id
- */
- @RequestLine("DELETE " + RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING
- + RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING + "/{dsId}")
- void unassignDistributionSet(@Param("dsTagId") final Long dsTagId, @Param("dsId") final Long dsId);
-}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetResource.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetResource.java
deleted file mode 100644
index 66c147426..000000000
--- a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetResource.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.mgmt.api.client;
-
-import java.util.List;
-
-import org.eclipse.hawkbit.rest.resource.model.target.TargetPagedList;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetRest;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
-
-import feign.Headers;
-import feign.Param;
-import feign.RequestLine;
-
-/**
- * Client binding for the Target resource of the management API.
- */
-public interface TargetResource {
-
- /**
- * Retrieves a single target based on the given ID.
- *
- * @param targetId
- * the ID of the target to retrieve
- * @return a deserialized java bean containing the attributes of the
- * returned target
- */
- @RequestLine("GET /rest/v1/targets/{targetId}")
- TargetRest getTarget(@Param("targetId") final String targetId);
-
- /**
- * Paged query of targets resource.
- *
- * @param pagingOffsetParam
- * of the paged query
- * @param pagingLimitParam
- * of the paged query
- * @return paged list of target entries
- */
- @RequestLine("GET /rest/v1/targets?offset={pagingOffsetParam}&limit={pagingLimitParam}")
- TargetPagedList getTargets(@Param("pagingOffsetParam") int pagingOffsetParam,
- @Param("pagingLimitParam") int pagingLimitParam);
-
- /**
- * Paged query of targets resource with default offset and limit.
- *
- * @return paged list of target entries
- */
- @RequestLine("GET /rest/v1/targets")
- TargetPagedList getTargets();
-
- /**
- * Deletes given target based on given ID.
- *
- * @param targetId
- * to be deleted
- */
- @RequestLine("DELETE /rest/v1/targets/{targetId}")
- void deleteTarget(@Param("targetId") final String targetId);
-
- /**
- * Creates a list of targets.
- *
- * @param targets
- * the request body java bean containing the necessary attributes
- * for creating a target.
- * @return the list of targets which have been created
- */
- @RequestLine("POST /rest/v1/targets/")
- @Headers("Content-Type: application/json")
- TargetsRest createTargets(List targets);
-
-}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagResource.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagResource.java
deleted file mode 100644
index bd74e52d7..000000000
--- a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagResource.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.mgmt.api.client;
-
-import java.util.List;
-
-import org.eclipse.hawkbit.rest.resource.RestConstants;
-import org.eclipse.hawkbit.rest.resource.model.tag.AssignedTargetRequestBody;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.TargetTagAssigmentResultRest;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
-
-import feign.Headers;
-import feign.Param;
-import feign.RequestLine;
-
-/**
- * Client binding for the Target resource of the management API.
- */
-public interface TargetTagResource {
-
- /**
- * Retrieves a single target tag based on the given ID.
- *
- * @param targetTagId
- * the ID of the target tag to retrieve
- * @return a deserialized java bean containing the attributes of the
- * returned target tag
- */
- @RequestLine("GET " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/{targetTagId}")
- TagRest getTargetTag(@Param("targetTagId") Long targetTagId);
-
- /**
- * Creates a list of target tags.
- *
- * @param tags
- * the tags to be created
- * @return the created tag list
- */
- @RequestLine("POST " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING)
- @Headers("Content-Type: application/json")
- TagsRest createTargetTag(List tags);
-
- /**
- * Update attributes of a target tag.
- *
- * @param targetTagId
- * the target tag id to be updated
- * @param tag
- * the request body
- * @return the updated target tag
- */
- @RequestLine("PUT " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/{targetTagId}")
- @Headers("Content-Type: application/json")
- TagRest updateTagretTag(@Param("targetTagId") Long targetTagId, TagRequestBodyPut tag);
-
- /**
- * Deletes given target tag on given ID.
- *
- * @param targetTagId
- * to be deleted
- */
- @RequestLine("DELETE " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING + "/{targetTagId}")
- void deleteTargetTag(@Param("targetTagId") final Long targetTagId);
-
- /**
- * Retrieves a all assigned targets on the given target tag id.
- *
- * @param targetTagId
- * the ID of the target tag to retrieve
- * @return a list of targets
- */
- @RequestLine("GET " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
- + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
- TargetsRest getAssignedTargets(@Param("targetTagId") final Long targetTagId);
-
- /**
- * Toggle the tag assignment all assigned targets will be unassigned and all
- * unassigned targets will be assigned.
- *
- * @param targetTagId
- * the ID of the target tag to toggle
- * @param assignedTargetRequestBodies
- * a list of controller ids
- * @return a list of assigned and unassigned targets
- */
- @RequestLine("POST " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
- + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING + "/toggleTagAssignment")
- @Headers("Content-Type: application/json")
- TargetTagAssigmentResultRest toggleTagAssignment(@Param("targetTagId") final Long targetTagId,
- final List assignedTargetRequestBodies);
-
- /**
- * Assign targets to a given target tag id.
- *
- * @param targetTagId
- * the ID of the target tag to add the targets
- * @param assignedTargetRequestBodies
- * a list of controller ids
- * @return a list of assigned targets
- */
- @RequestLine("POST " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
- + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
- @Headers("Content-Type: application/json")
- TargetsRest assignTargets(@Param("targetTagId") final Long targetTagId,
- final List assignedTargetRequestBodies);
-
- /**
- * Unassign targets to a given target tag id.
- *
- * @param targetTagId
- * the ID of the target tag to add the targets
- */
- @RequestLine("DELETE " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
- + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
- void unassignTargets(@Param("targetTagId") final Long targetTagId);
-
- /**
- * Unassign one target to a given target tag id.
- *
- * @param targetTagId
- * the ID of the target tag to add the targets param
- * @param controllerId
- * the controller id
- */
- @RequestLine("DELETE " + RestConstants.TARGET_TAG_V1_REQUEST_MAPPING
- + RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING + "/{controllerId}")
- void unassignTarget(@Param("targetTagId") final Long targetTagId, @Param("controllerId") final String controllerId);
-}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java
new file mode 100644
index 000000000..27584b50a
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.client;
+
+import org.eclipse.hawkbit.mgmt.client.scenarios.CreateStartedRolloutExample;
+import org.eclipse.hawkbit.mgmt.client.scenarios.GettingStartedDefaultScenario;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+
+import feign.Contract;
+import feign.auth.BasicAuthRequestInterceptor;
+
+@SpringBootApplication
+@EnableFeignClients
+@EnableConfigurationProperties(ClientConfigurationProperties.class)
+public class Application implements CommandLineRunner {
+
+ @Autowired
+ private ClientConfigurationProperties configuration;
+
+ @Autowired
+ private GettingStartedDefaultScenario gettingStarted;
+
+ @Autowired
+ private CreateStartedRolloutExample gettingStartedRolloutScenario;
+
+ public static void main(final String[] args) {
+ new SpringApplicationBuilder().showBanner(false).sources(Application.class).run(args);
+ }
+
+ @Override
+ public void run(final String... args) throws Exception {
+ if (containsArg("--createrollout", args)) {
+ // run the create and start rollout example
+ gettingStartedRolloutScenario.run();
+ } else {
+ // run the getting started scenario which creates a setup of
+ // distribution set and software modules to be used
+ gettingStarted.run();
+ }
+ }
+
+ @Bean
+ public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
+ return new BasicAuthRequestInterceptor(configuration.getUsername(), configuration.getPassword());
+ }
+
+ @Bean
+ public ApplicationJsonRequestHeaderInterceptor jsonHeaderInterceptor() {
+ return new ApplicationJsonRequestHeaderInterceptor();
+ }
+
+ @Bean
+ public Contract feignContract() {
+ return new IgnoreMultipleConsumersProducersSpringMvcContract();
+ }
+
+ private boolean containsArg(final String containsArg, final String... args) {
+ for (final String arg : args) {
+ if (arg.equalsIgnoreCase(containsArg)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ApplicationJsonRequestHeaderInterceptor.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ApplicationJsonRequestHeaderInterceptor.java
new file mode 100644
index 000000000..75f3b0dd1
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ApplicationJsonRequestHeaderInterceptor.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.client;
+
+import org.springframework.http.MediaType;
+
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+
+/**
+ * An feign request interceptor to set the defined {@code Accept} and
+ * {@code Content-Type} headers for each request to {@code application/json}.
+ */
+public class ApplicationJsonRequestHeaderInterceptor implements RequestInterceptor {
+
+ @Override
+ public void apply(final RequestTemplate template) {
+ template.header("Accept", MediaType.APPLICATION_JSON_VALUE);
+ template.header("Content-Type", MediaType.APPLICATION_JSON_VALUE);
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java
new file mode 100644
index 000000000..6d15bcc04
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.client;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Configuration bean which holds the configuration of the client e.g. the base
+ * URL of the hawkbit-server and the credentials to use the RESTful Management
+ * API.
+ */
+@ConfigurationProperties(prefix = "hawkbit")
+public class ClientConfigurationProperties {
+
+ private String url = "localhost:8080";
+ private String username = "admin";
+ private String password = "admin"; // NOSONAR this password is only used for
+ // examples
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(final String url) {
+ this.url = url;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(final String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(final String password) {
+ this.password = password;
+ }
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/IgnoreMultipleConsumersProducersSpringMvcContract.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/IgnoreMultipleConsumersProducersSpringMvcContract.java
new file mode 100644
index 000000000..c796aa019
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/IgnoreMultipleConsumersProducersSpringMvcContract.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.client;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.netflix.feign.support.SpringMvcContract;
+
+import feign.MethodMetadata;
+
+/**
+ * Own implementation of the {@link SpringMvcContract} which catches the
+ * {@link IllegalStateException} which occurs due multiple produces and consumes
+ * values in the request-mapping
+ * annoation.https://github.com/spring-cloud/spring-cloud-netflix/issues/808
+ */
+public class IgnoreMultipleConsumersProducersSpringMvcContract extends SpringMvcContract {
+
+ private static final Logger LOGGER = LoggerFactory
+ .getLogger(IgnoreMultipleConsumersProducersSpringMvcContract.class);
+
+ @Override
+ protected void processAnnotationOnMethod(final MethodMetadata data, final Annotation methodAnnotation,
+ final Method method) {
+ try {
+ super.processAnnotationOnMethod(data, methodAnnotation, method);
+ } catch (final IllegalStateException e) {
+ // ignore illegalstateexception here because it's thrown because of
+ // multiple consumers and produces, see
+ // https://github.com/spring-cloud/spring-cloud-netflix/issues/808
+ LOGGER.trace(e.getMessage(), e);
+ }
+ }
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/DistributionSetResourceClient.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/DistributionSetResourceClient.java
new file mode 100644
index 000000000..00a9b3fba
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/DistributionSetResourceClient.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.client.resource;
+
+import org.eclipse.hawkbit.rest.resource.api.DistributionSetRestApi;
+import org.springframework.cloud.netflix.feign.FeignClient;
+
+/**
+ * Client binding for the DistributionSet resource of the management API.
+ */
+@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/distributionsets")
+public interface DistributionSetResourceClient extends DistributionSetRestApi {
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/DistributionSetTagResourceClient.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/DistributionSetTagResourceClient.java
new file mode 100644
index 000000000..ea9f5d28a
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/DistributionSetTagResourceClient.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.client.resource;
+
+import org.eclipse.hawkbit.rest.resource.api.DistributionSetTagRestApi;
+import org.springframework.cloud.netflix.feign.FeignClient;
+
+/**
+ * Client binding for the DistributionSetTag resource of the management API.
+ */
+@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/distributionsettags")
+public interface DistributionSetTagResourceClient extends DistributionSetTagRestApi {
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/DistributionSetTypeResourceClient.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/DistributionSetTypeResourceClient.java
new file mode 100644
index 000000000..78e3df1c2
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/DistributionSetTypeResourceClient.java
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource;
+
+import org.eclipse.hawkbit.rest.resource.api.DistributionSetTypeRestApi;
+import org.springframework.cloud.netflix.feign.FeignClient;
+
+/**
+ * Client binding for the DistributionSetType resource of the management API.
+ *
+ */
+@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/distributionsettypes")
+public interface DistributionSetTypeResourceClient extends DistributionSetTypeRestApi {
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/RolloutResourceClient.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/RolloutResourceClient.java
new file mode 100644
index 000000000..0124bb383
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/RolloutResourceClient.java
@@ -0,0 +1,15 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource;
+
+import org.eclipse.hawkbit.rest.resource.api.RolloutRestApi;
+import org.springframework.cloud.netflix.feign.FeignClient;
+
+/**
+ * Client binding for the Rollout resource of the management API.
+ */
+@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/rollouts")
+public interface RolloutResourceClient extends RolloutRestApi {
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/SoftwareModuleResourceClient.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/SoftwareModuleResourceClient.java
new file mode 100644
index 000000000..9ffbe2a1a
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/SoftwareModuleResourceClient.java
@@ -0,0 +1,15 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource;
+
+import org.eclipse.hawkbit.rest.resource.api.SoftwareModuleRestAPI;
+import org.springframework.cloud.netflix.feign.FeignClient;
+
+/**
+ * Client binding for the SoftwareModule resource of the management API.
+ */
+@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/softwaremodules")
+public interface SoftwareModuleResourceClient extends SoftwareModuleRestAPI {
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/SoftwareModuleTypeResourceClient.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/SoftwareModuleTypeResourceClient.java
new file mode 100644
index 000000000..4896cb8d8
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/SoftwareModuleTypeResourceClient.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.client.resource;
+
+import org.eclipse.hawkbit.rest.resource.api.SoftwareModuleTypeRestApi;
+import org.springframework.cloud.netflix.feign.FeignClient;
+
+/**
+ * Client binding for the oftwareModuleType resource of the management API.
+ */
+@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/softwaremoduletypes")
+public interface SoftwareModuleTypeResourceClient extends SoftwareModuleTypeRestApi {
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/TargetResourceClient.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/TargetResourceClient.java
new file mode 100644
index 000000000..a82aa5443
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/TargetResourceClient.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.client.resource;
+
+import org.eclipse.hawkbit.rest.resource.api.TargetRestApi;
+import org.springframework.cloud.netflix.feign.FeignClient;
+
+/**
+ * Client binding for the Target resource of the management API.
+ */
+@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/targets")
+public interface TargetResourceClient extends TargetRestApi {
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/TargetTagResourceClient.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/TargetTagResourceClient.java
new file mode 100644
index 000000000..fee30c686
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/TargetTagResourceClient.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.mgmt.client.resource;
+
+import org.eclipse.hawkbit.rest.resource.api.TargetTagRestApi;
+import org.springframework.cloud.netflix.feign.FeignClient;
+
+/**
+ * Client binding for the TargetTag resource of the management API.
+ */
+@FeignClient(url = "${hawkbit.endpoint.url:localhost:8080}/rest/v1/targettags")
+public interface TargetTagResourceClient extends TargetTagRestApi {
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java
new file mode 100644
index 000000000..772256175
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRequestBodyPost;
+
+import com.google.common.collect.Lists;
+
+/**
+ *
+ * Builder pattern for building {@link DistributionSetRequestBodyPost}.
+ *
+ * @author Jonathan Knoblauch
+ *
+ */
+public class DistributionSetBuilder {
+
+ private String name;
+ private String version;
+ private String type;
+
+ /**
+ * @param name
+ * the name of the distribution set
+ * @return the builder itself
+ */
+ public DistributionSetBuilder name(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param version
+ * the version of the distribution set
+ * @return the builder itself
+ */
+ public DistributionSetBuilder version(final String version) {
+ this.version = version;
+ return this;
+ }
+
+ /**
+ * @param type
+ * the distribution set type name for this distribution set
+ * @return the builder itself
+ */
+ public DistributionSetBuilder type(final String type) {
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * Builds a list with a single entry of
+ * {@link DistributionSetRequestBodyPost} which can directly be used to post
+ * on the RESTful-API.
+ *
+ * @return a single entry list of {@link DistributionSetRequestBodyPost}
+ */
+ public List build() {
+ return Lists.newArrayList(doBuild(name));
+ }
+
+ /**
+ * Builds a list of multiple {@link DistributionSetRequestBodyPost} to
+ * create multiple distribution sets at once. An increasing number will be
+ * added to the name of the distribution set. The version and type will
+ * remain the same.
+ *
+ * @param count
+ * the amount of distribution sets body which should be created
+ * @return a list of {@link DistributionSetRequestBodyPost}
+ */
+ public List buildAsList(final int count) {
+ final ArrayList bodyList = Lists.newArrayList();
+ for (int index = 0; index < count; index++) {
+ bodyList.add(doBuild(name + index));
+ }
+
+ return bodyList;
+ }
+
+ private DistributionSetRequestBodyPost doBuild(final String prefixName) {
+ final DistributionSetRequestBodyPost body = new DistributionSetRequestBodyPost();
+ body.setName(prefixName);
+ body.setVersion(version);
+ body.setType(type);
+ return body;
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java
new file mode 100644
index 000000000..0ba326c16
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeAssigmentRest;
+
+import com.google.common.collect.Lists;
+
+/**
+ *
+ * Builder pattern for building {@link DistributionSetTypeRequestBodyPost}.
+ *
+ * @author Jonathan Knoblauch
+ *
+ */
+public class DistributionSetTypeBuilder {
+
+ private String key;
+ private String name;
+ private final List mandatorymodules = Lists.newArrayList();
+ private final List optionalmodules = Lists.newArrayList();
+
+ /**
+ * @param key
+ * the key of the distribution set type
+ * @return the builder itself
+ */
+ public DistributionSetTypeBuilder key(final String key) {
+ this.key = key;
+ return this;
+ }
+
+ /**
+ * @param name
+ * the name of the distribution set type
+ * @return the builder itself
+ */
+ public DistributionSetTypeBuilder name(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param softwareModuleTypeIds
+ * the IDs of the software module types which should be mandatory
+ * for the distribution set type
+ * @return the builder itself
+ */
+ public DistributionSetTypeBuilder mandatorymodules(final Long... softwareModuleTypeIds) {
+ for (final Long id : softwareModuleTypeIds) {
+ final SoftwareModuleTypeAssigmentRest softwareModuleTypeAssigmentRest = new SoftwareModuleTypeAssigmentRest();
+ softwareModuleTypeAssigmentRest.setId(id);
+ this.mandatorymodules.add(softwareModuleTypeAssigmentRest);
+ }
+ return this;
+ }
+
+ /**
+ *
+ * @param softwareModuleTypeIds
+ * the IDs of the software module types which should be optional
+ * for the distribution set type
+ * @return the builder itself
+ */
+ public DistributionSetTypeBuilder optionalmodules(final Long... softwareModuleTypeIds) {
+ for (final Long id : softwareModuleTypeIds) {
+ final SoftwareModuleTypeAssigmentRest softwareModuleTypeAssigmentRest = new SoftwareModuleTypeAssigmentRest();
+ softwareModuleTypeAssigmentRest.setId(id);
+ this.optionalmodules.add(softwareModuleTypeAssigmentRest);
+ }
+ return this;
+ }
+
+ /**
+ * Builds a list with a single entry of
+ * {@link DistributionSetTypeRequestBodyPost} which can directly be used in
+ * the RESTful-API.
+ *
+ * @return a single entry list of {@link DistributionSetTypeRequestBodyPost}
+ */
+ public List build() {
+ return Lists.newArrayList(doBuild(name, key));
+ }
+
+ /**
+ * Builds a list of multiple {@link DistributionSetTypeRequestBodyPost} to
+ * create multiple distribution set types at once. An increasing number will
+ * be added to the name and key of the distribution set type. The optional
+ * and mandatory software module types will remain the same.
+ *
+ * @param count
+ * the amount of distribution sets type body which should be
+ * created
+ * @return a list of {@link DistributionSetTypeRequestBodyPost}
+ */
+ public List buildAsList(final int count) {
+ final ArrayList bodyList = Lists.newArrayList();
+ for (int index = 0; index < count; index++) {
+ bodyList.add(doBuild(name + index, key + index));
+ }
+ return bodyList;
+
+ }
+
+ private DistributionSetTypeRequestBodyPost doBuild(final String prefixName, final String prefixKey) {
+ final DistributionSetTypeRequestBodyPost body = new DistributionSetTypeRequestBodyPost();
+ body.setKey(prefixKey);
+ body.setName(prefixName);
+ body.setMandatorymodules(mandatorymodules);
+ body.setOptionalmodules(optionalmodules);
+ return body;
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/RolloutBuilder.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/RolloutBuilder.java
new file mode 100644
index 000000000..73f327db9
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/RolloutBuilder.java
@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource.builder;
+
+import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutCondition;
+import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutCondition.Condition;
+import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutRestRequestBody;
+
+/**
+ *
+ * Builder pattern for building {@link RolloutRestRequestBody}.
+ *
+ * @author Jonathan Knoblauch
+ *
+ */
+public class RolloutBuilder {
+
+ private String name;
+ private int groupSize;
+ private String targetFilterQuery;
+ private long distributionSetId;
+ private String successThreshold;
+ private String errorThreshold;
+
+ /**
+ * @param name
+ * the name of the rollout
+ * @return the builder itself
+ */
+ public RolloutBuilder name(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param groupSize
+ * the amount of groups the rollout should be split into
+ * @return the builder itself
+ */
+ public RolloutBuilder groupSize(final int groupSize) {
+ this.groupSize = groupSize;
+ return this;
+ }
+
+ /**
+ * @param targetFilterQuery
+ * the FIQL query language to filter targets to contain in the
+ * rollout
+ * @return the builder itself
+ */
+ public RolloutBuilder targetFilterQuery(final String targetFilterQuery) {
+ this.targetFilterQuery = targetFilterQuery;
+ return this;
+ }
+
+ /**
+ * @param distributionSetId
+ * the ID of the distribution set to assign to the target in the
+ * rollout
+ * @return the builder itself
+ */
+ public RolloutBuilder distributionSetId(final long distributionSetId) {
+ this.distributionSetId = distributionSetId;
+ return this;
+ }
+
+ /**
+ * @param successThreshold
+ * the threshold to be used to indicate if a deployment group is
+ * successful, to trigger the success action
+ * @return the builder itself
+ */
+ public RolloutBuilder successThreshold(final String successThreshold) {
+ this.successThreshold = successThreshold;
+ return this;
+ }
+
+ /**
+ * @param errorThreshold
+ * the threshold to be used to indicate if a deployment group is
+ * failing, to trigger the error action
+ * @return the builder itself
+ */
+ public RolloutBuilder errorThreshold(final String errorThreshold) {
+ this.errorThreshold = errorThreshold;
+ return this;
+ }
+
+ /**
+ * Builds the rollout rest body to creating a rollout.
+ *
+ * @return the rest request body for creating a rollout
+ */
+ public RolloutRestRequestBody build() {
+ return doBuild();
+ }
+
+ private RolloutRestRequestBody doBuild() {
+ final RolloutRestRequestBody body = new RolloutRestRequestBody();
+ body.setName(name);
+ body.setAmountGroups(groupSize);
+ body.setTargetFilterQuery(targetFilterQuery);
+ body.setDistributionSetId(distributionSetId);
+ body.setSuccessCondition(new RolloutCondition(Condition.THRESHOLD, successThreshold));
+ body.setErrorCondition(new RolloutCondition(Condition.THRESHOLD, errorThreshold));
+ return body;
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleAssigmentBuilder.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleAssigmentBuilder.java
new file mode 100644
index 000000000..0086ae93b
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleAssigmentBuilder.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleAssigmentRest;
+
+/**
+ *
+ * Builder pattern for building {@link SoftwareModuleAssigmentRest}.
+ *
+ * @author Jonathan Knoblauch
+ *
+ */
+public class SoftwareModuleAssigmentBuilder {
+
+ private final List ids;
+
+ public SoftwareModuleAssigmentBuilder() {
+ ids = new ArrayList();
+ }
+
+ /**
+ * @param id
+ * the id of the software module
+ * @return the builder itself
+ */
+ public SoftwareModuleAssigmentBuilder id(final Long id) {
+ ids.add(id);
+ return this;
+ }
+
+ /**
+ * Builds a list with a single entry of {@link SoftwareModuleAssigmentRest}
+ * which can directly be used in the RESTful-API.
+ *
+ * @return a single entry list of {@link SoftwareModuleAssigmentRest}
+ */
+ public List build() {
+ final List softwareModuleAssigmentRestList = new ArrayList<>();
+ for (final Long id : ids) {
+ final SoftwareModuleAssigmentRest softwareModuleAssigmentRest = new SoftwareModuleAssigmentRest();
+ softwareModuleAssigmentRest.setId(id);
+ softwareModuleAssigmentRestList.add(softwareModuleAssigmentRest);
+ }
+ return softwareModuleAssigmentRestList;
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java
new file mode 100644
index 000000000..f293e910f
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRequestBodyPost;
+
+import com.google.common.collect.Lists;
+
+/**
+ *
+ * Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
+ *
+ * @author Jonathan Knoblauch
+ *
+ */
+public class SoftwareModuleBuilder {
+
+ private String name;
+ private String version;
+ private String type;
+
+ /**
+ * @param name
+ * the name of the software module
+ * @return the builder itself
+ */
+ public SoftwareModuleBuilder name(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param version
+ * the version of the software module
+ * @return the builder itsefl
+ */
+ public SoftwareModuleBuilder version(final String version) {
+ this.version = version;
+ return this;
+ }
+
+ /**
+ * @param type
+ * the key of the software module type to be used for this
+ * software module
+ * @return the builder itself
+ */
+ public SoftwareModuleBuilder type(final String type) {
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * Builds a list with a single entry of
+ * {@link SoftwareModuleRequestBodyPost} which can directly be used in the
+ * RESTful-API.
+ *
+ * @return a single entry list of {@link SoftwareModuleRequestBodyPost}
+ */
+ public List build() {
+ return Lists.newArrayList(doBuild(name));
+ }
+
+ /**
+ * Builds a list of multiple {@link SoftwareModuleRequestBodyPost} to create
+ * multiple software module at once. An increasing number will be added to
+ * the name of the software module. The version and type will remain the
+ * same.
+ *
+ * @param count
+ * the amount of software module body which should be created
+ * @return a list of {@link DistributionSetTypeRequestBodyPost}
+ */
+ public List buildAsList(final int count) {
+ final ArrayList bodyList = Lists.newArrayList();
+ for (int index = 0; index < count; index++) {
+ bodyList.add(doBuild(name + index));
+ }
+
+ return bodyList;
+ }
+
+ private SoftwareModuleRequestBodyPost doBuild(final String prefixName) {
+ final SoftwareModuleRequestBodyPost body = new SoftwareModuleRequestBodyPost();
+ body.setName(prefixName);
+ body.setVersion(version);
+ body.setType(type);
+ return body;
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java
new file mode 100644
index 000000000..7222dc522
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRequestBodyPost;
+
+import com.google.common.collect.Lists;
+
+/**
+ *
+ * Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
+ *
+ * @author Jonathan Knoblauch
+ *
+ */
+public class SoftwareModuleTypeBuilder {
+
+ private String key;
+ private String name;
+ private String description;
+ private int maxAssignments;
+
+ /**
+ * @param key
+ * the key of the software module type
+ * @return the builder itself
+ */
+ public SoftwareModuleTypeBuilder key(final String key) {
+ this.key = key;
+ return this;
+ }
+
+ /**
+ * @param name
+ * the name of the software module type
+ * @return the builder itself
+ */
+ public SoftwareModuleTypeBuilder name(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ public SoftwareModuleTypeBuilder description(final String description) {
+ this.description = description;
+ return this;
+ }
+
+ public SoftwareModuleTypeBuilder maxAssignments(final int maxAssignments) {
+ this.maxAssignments = maxAssignments;
+ return this;
+ }
+
+ /**
+ * Builds a list with a single entry of
+ * {@link SoftwareModuleTypeRequestBodyPost} which can directly be used in
+ * the RESTful-API.
+ *
+ * @return a single entry list of {@link SoftwareModuleTypeRequestBodyPost}
+ */
+ public List build() {
+ return Lists.newArrayList(doBuild(key, name));
+ }
+
+ /**
+ * Builds a list of multiple {@link SoftwareModuleTypeRequestBodyPost} to
+ * create multiple software module types at once. An increasing number will
+ * be added to the name and key of the software module type.
+ *
+ * @param count
+ * the amount of software module type bodies which should be
+ * created
+ * @return a list of {@link SoftwareModuleTypeRequestBodyPost}
+ */
+ public List buildAsList(final int count) {
+ final ArrayList bodyList = Lists.newArrayList();
+ for (int index = 0; index < count; index++) {
+ bodyList.add(doBuild(key + index, name + index));
+ }
+ return bodyList;
+ }
+
+ private SoftwareModuleTypeRequestBodyPost doBuild(final String prefixKey, final String prefixName) {
+ final SoftwareModuleTypeRequestBodyPost body = new SoftwareModuleTypeRequestBodyPost();
+ body.setKey(prefixKey);
+ body.setName(prefixName);
+ body.setDescription(description);
+ body.setMaxAssignments(maxAssignments);
+ return body;
+ }
+
+}
\ No newline at end of file
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TagBuilder.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TagBuilder.java
new file mode 100644
index 000000000..af2926337
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TagBuilder.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Builder pattern for building {@link TagRequestBodyPut}.
+ *
+ * @author Jonathan Knoblauch
+ *
+ */
+public class TagBuilder {
+
+ private String name;
+ private String description;
+ private String color;
+
+ /**
+ * @param name
+ * the name of the tag
+ * @return the builder itself
+ */
+ public TagBuilder name(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param description
+ * the description of the tag
+ * @return the builder itself
+ */
+ public TagBuilder description(final String description) {
+ this.description = description;
+ return this;
+ }
+
+ /**
+ * @param color
+ * the colour of the tag
+ * @return the builder itself
+ */
+ public TagBuilder color(final String color) {
+ this.color = color;
+ return this;
+ }
+
+ /**
+ * Builds a list with a single entry of {@link TagRequestBodyPut} which can
+ * directly be used in the RESTful-API.
+ *
+ * @return a single entry list of {@link TagRequestBodyPut}
+ */
+ public List build() {
+ return Lists.newArrayList(doBuild(name));
+ }
+
+ /**
+ * Builds a list of multiple {@link TagRequestBodyPut} to create multiple
+ * tags at once. An increasing number will be added to the name of the tag.
+ * The color and description will remain the same.
+ *
+ * @param count
+ * the amount of distribution sets body which should be created
+ * @return a list of {@link TagRequestBodyPut}
+ */
+ public List buildAsList(final int count) {
+ final ArrayList bodyList = Lists.newArrayList();
+ for (int index = 0; index < count; index++) {
+ bodyList.add(doBuild(name + index));
+ }
+
+ return bodyList;
+ }
+
+ private TagRequestBodyPut doBuild(final String prefixName) {
+ final TagRequestBodyPut body = new TagRequestBodyPut();
+ body.setName(prefixName);
+ body.setDescription(description);
+ body.setColour(color);
+ return body;
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java
new file mode 100644
index 000000000..15e970fba
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.resource.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
+
+import com.google.common.collect.Lists;
+
+/**
+ *
+ * Builder pattern for building {@link TargetRequestBody}.
+ *
+ * @author Jonathan Knoblauch
+ *
+ */
+public class TargetBuilder {
+
+ private String controllerId;
+ private String name;
+ private String description;
+
+ /**
+ * @param controllerId
+ * the ID of the controller/target
+ * @return the builder itself
+ */
+ public TargetBuilder controllerId(final String controllerId) {
+ this.controllerId = controllerId;
+ return this;
+ }
+
+ /**
+ * @param name
+ * the name of the target
+ * @return the builder itself
+ */
+ public TargetBuilder name(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param description
+ * the description of the target
+ * @return the builder itself
+ */
+ public TargetBuilder description(final String description) {
+ this.description = description;
+ return this;
+ }
+
+ /**
+ * Builds a list with a single entry of {@link TargetRequestBody} which can
+ * directly be used in the RESTful-API.
+ *
+ * @return a single entry list of {@link TargetRequestBody}
+ */
+ public List build() {
+ return Lists.newArrayList(doBuild(controllerId));
+ }
+
+ /**
+ * Builds a list of multiple {@link TargetRequestBody} to create multiple
+ * targets at once. An increasing number will be added to the controllerId
+ * of the target. The name and description will remain.
+ *
+ * @param count
+ * the amount of software module type bodies which should be
+ * created
+ * @return a list of {@link SoftwareModuleTypeRequestBodyPost}
+ */
+ public List buildAsList(final int count) {
+ final ArrayList bodyList = Lists.newArrayList();
+ for (int index = 0; index < count; index++) {
+ bodyList.add(doBuild(controllerId + index));
+ }
+ return bodyList;
+ }
+
+ private TargetRequestBody doBuild(final String prefixControllerId) {
+ final TargetRequestBody body = new TargetRequestBody();
+ body.setControllerId(prefixControllerId);
+ body.setName(name);
+ body.setDescription(description);
+ return body;
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java
new file mode 100644
index 000000000..1414281ee
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.mgmt.client.scenarios;
+
+import org.eclipse.hawkbit.mgmt.client.resource.DistributionSetResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.DistributionSetTypeResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.RolloutResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.SoftwareModuleResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.SoftwareModuleTypeResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.TargetResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetTypeBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.RolloutBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleTypeBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.TargetBuilder;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
+import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutResponseBody;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModulesRest;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypesRest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Example for creating and starting a Rollout.
+ *
+ */
+@Component
+public class CreateStartedRolloutExample {
+
+ /* known software module type name and key */
+ private static final String SM_MODULE_TYPE = "firmware";
+
+ /* known distribution set type name and key */
+ private static final String DS_MODULE_TYPE = "firmware";
+
+ @Autowired
+ private DistributionSetResourceClient distributionSetResource;
+
+ @Autowired
+ private SoftwareModuleResourceClient softwareModuleResource;
+
+ @Autowired
+ private TargetResourceClient targetResource;
+
+ @Autowired
+ private RolloutResourceClient rolloutResource;
+
+ @Autowired
+ private DistributionSetTypeResourceClient distributionSetTypeResource;
+
+ @Autowired
+ private SoftwareModuleTypeResourceClient softwareModuleTypeResource;
+
+ /**
+ * Run the Rollout scenario.
+ */
+ public void run() {
+
+ // create three SoftwareModuleTypes
+ final SoftwareModuleTypesRest createdSoftwareModuleTypes = softwareModuleTypeResource.createSoftwareModuleTypes(
+ new SoftwareModuleTypeBuilder().key(SM_MODULE_TYPE).name(SM_MODULE_TYPE).maxAssignments(1).build())
+ .getBody();
+
+ // create one DistributionSetType
+ distributionSetTypeResource.createDistributionSetTypes(new DistributionSetTypeBuilder().key(DS_MODULE_TYPE)
+ .name(DS_MODULE_TYPE).mandatorymodules(createdSoftwareModuleTypes.get(0).getModuleId()).build())
+ .getBody();
+
+ // create one DistributionSet
+ final DistributionSetsRest distributionSetsRest = distributionSetResource.createDistributionSets(
+ new DistributionSetBuilder().name("rollout-example").version("1.0.0").type(DS_MODULE_TYPE).build())
+ .getBody();
+
+ // create three SoftwareModules
+ final SoftwareModulesRest softwareModulesRest = softwareModuleResource
+ .createSoftwareModules(
+ new SoftwareModuleBuilder().name("firmware").version("1.0.0").type(SM_MODULE_TYPE).build())
+ .getBody();
+
+ // Assign SoftwareModule to DistributionSet
+ distributionSetResource.assignSoftwareModules(distributionSetsRest.get(0).getDsId(),
+ new SoftwareModuleAssigmentBuilder().id(softwareModulesRest.get(0).getModuleId()).build());
+
+ // create ten targets
+ targetResource.createTargets(new TargetBuilder().controllerId("00-FF-AA-0").name("00-FF-AA-0")
+ .description("Targets used for rollout example").buildAsList(10));
+
+ // create a Rollout
+ final RolloutResponseBody rolloutResponseBody = rolloutResource
+ .create(new RolloutBuilder().name("MyRollout").groupSize(2).targetFilterQuery("name==00-FF-AA-0*")
+ .distributionSetId(distributionSetsRest.get(0).getDsId()).successThreshold("80")
+ .errorThreshold("50").build())
+ .getBody();
+
+ // start the created Rollout
+ rolloutResource.start(rolloutResponseBody.getRolloutId(), false);
+ }
+
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/GettingStartedDefaultScenario.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/GettingStartedDefaultScenario.java
new file mode 100644
index 000000000..2d3e071ed
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/GettingStartedDefaultScenario.java
@@ -0,0 +1,126 @@
+package org.eclipse.hawkbit.mgmt.client.scenarios;
+
+import org.eclipse.hawkbit.mgmt.client.resource.DistributionSetResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.DistributionSetTypeResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.SoftwareModuleResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.SoftwareModuleTypeResourceClient;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetTypeBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder;
+import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleTypeBuilder;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModulesRest;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypesRest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * Default getting started scenario.
+ *
+ */
+@Component
+public class GettingStartedDefaultScenario {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(GettingStartedDefaultScenario.class);
+
+ /* known software module type name and key */
+ private static final String SM_MODULE_TYPE = "gettingstarted";
+
+ /* known distribution set type name and key */
+ private static final String DS_MODULE_TYPE = "gettingstarted";
+
+ /* known distribution name of this getting started example */
+ private static final String SM_EXAMPLE_NAME = "gettingstarted-example";
+
+ /* known distribution name of this getting started example */
+ private static final String DS_EXAMPLE_NAME = "gettingstarted-example";
+
+ @Autowired
+ private DistributionSetResourceClient distributionSetResource;
+
+ @Autowired
+ private DistributionSetTypeResourceClient distributionSetTypeResource;
+
+ @Autowired
+ private SoftwareModuleResourceClient softwareModuleResource;
+
+ @Autowired
+ private SoftwareModuleTypeResourceClient softwareModuleTypeResource;
+
+ /**
+ * Run the default getting started scenario.
+ */
+ public void run() {
+
+ LOGGER.info("Running Getting-Started-Scenario...");
+
+ // create one SoftwareModuleTypes
+ LOGGER.info("Creating software module type {}", SM_MODULE_TYPE);
+ final SoftwareModuleTypesRest createdSoftwareModuleTypes = softwareModuleTypeResource.createSoftwareModuleTypes(
+ new SoftwareModuleTypeBuilder().key(SM_MODULE_TYPE).name(SM_MODULE_TYPE).maxAssignments(1).build())
+ .getBody();
+
+ // create one DistributionSetType
+ LOGGER.info("Creating distribution set type {}", DS_MODULE_TYPE);
+ distributionSetTypeResource.createDistributionSetTypes(new DistributionSetTypeBuilder().key(DS_MODULE_TYPE)
+ .name(DS_MODULE_TYPE).mandatorymodules(createdSoftwareModuleTypes.get(0).getModuleId()).build());
+
+ // create three DistributionSet
+ final String dsVersion1 = "1.0.0";
+ final String dsVersion2 = "2.0.0";
+ final String dsVersion3 = "2.1.0";
+
+ LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion1);
+ final DistributionSetsRest distributionSetsRest1 = distributionSetResource.createDistributionSets(
+ new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion1).type(DS_MODULE_TYPE).build())
+ .getBody();
+
+ LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion2);
+ final DistributionSetsRest distributionSetsRest2 = distributionSetResource.createDistributionSets(
+ new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion2).type(DS_MODULE_TYPE).build())
+ .getBody();
+
+ LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion3);
+ final DistributionSetsRest distributionSetsRest3 = distributionSetResource.createDistributionSets(
+ new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion3).type(DS_MODULE_TYPE).build())
+ .getBody();
+
+ // create three SoftwareModules
+ final String swVersion1 = "1";
+ final String swVersion2 = "2";
+ final String swVersion3 = "3";
+
+ LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion1);
+ final SoftwareModulesRest softwareModulesRest1 = softwareModuleResource.createSoftwareModules(
+ new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion1).type(SM_MODULE_TYPE).build())
+ .getBody();
+ LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion2);
+ final SoftwareModulesRest softwareModulesRest2 = softwareModuleResource.createSoftwareModules(
+ new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion2).type(SM_MODULE_TYPE).build())
+ .getBody();
+ LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion3);
+ final SoftwareModulesRest softwareModulesRest3 = softwareModuleResource.createSoftwareModules(
+ new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion3).type(SM_MODULE_TYPE).build())
+ .getBody();
+
+ // Assign SoftwareModules to DistributionSet
+ LOGGER.info("Assign software module {}:{} to distribution set {}:{}", SM_EXAMPLE_NAME, swVersion1,
+ DS_EXAMPLE_NAME, dsVersion1);
+ distributionSetResource.assignSoftwareModules(distributionSetsRest1.get(0).getDsId(),
+ new SoftwareModuleAssigmentBuilder().id(softwareModulesRest1.get(0).getModuleId()).build());
+
+ LOGGER.info("Assign software module {}:{} to distribution set {}:{}", SM_EXAMPLE_NAME, swVersion2,
+ DS_EXAMPLE_NAME, dsVersion2);
+ distributionSetResource.assignSoftwareModules(distributionSetsRest2.get(0).getDsId(),
+ new SoftwareModuleAssigmentBuilder().id(softwareModulesRest2.get(0).getModuleId()).build());
+
+ LOGGER.info("Assign software module {}:{} to distribution set {}:{}", SM_EXAMPLE_NAME, swVersion3,
+ DS_EXAMPLE_NAME, dsVersion3);
+ distributionSetResource.assignSoftwareModules(distributionSetsRest3.get(0).getDsId(),
+ new SoftwareModuleAssigmentBuilder().id(softwareModulesRest3.get(0).getModuleId()).build());
+ }
+}
diff --git a/examples/hawkbit-mgmt-api-client/src/main/resources/application.properties b/examples/hawkbit-mgmt-api-client/src/main/resources/application.properties
new file mode 100644
index 000000000..93eb7e982
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/resources/application.properties
@@ -0,0 +1,6 @@
+logging.level=trace
+hawkbit.url=localhost:8080
+hawkbit.username=admin
+hawkbit.password=admin
+
+spring.main.banner-mode=OFF
\ No newline at end of file
diff --git a/examples/hawkbit-mgmt-api-client/src/main/resources/logback.xml b/examples/hawkbit-mgmt-api-client/src/main/resources/logback.xml
new file mode 100644
index 000000000..1c76f642a
--- /dev/null
+++ b/examples/hawkbit-mgmt-api-client/src/main/resources/logback.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetTagTest.java b/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetTagTest.java
deleted file mode 100644
index 17384c211..000000000
--- a/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/DistributionSetTagTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.mgmt.api.client;
-
-import static org.fest.assertions.api.Assertions.assertThat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.hawkbit.app.Start;
-import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRequestBodyPost;
-import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRest;
-import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.AssignedDistributionSetRequestBody;
-import org.eclipse.hawkbit.rest.resource.model.tag.DistributionSetTagAssigmentResultRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.springframework.boot.SpringApplication;
-import org.springframework.context.annotation.Description;
-
-import ru.yandex.qatools.allure.annotations.Features;
-import ru.yandex.qatools.allure.annotations.Stories;
-import feign.Feign;
-import feign.Logger;
-import feign.auth.BasicAuthRequestInterceptor;
-import feign.jackson.JacksonDecoder;
-import feign.jackson.JacksonEncoder;
-
-@Features("Example Tests - Management RESTful API Client")
-@Stories("DistrubutionSet Tag Resource")
-public class DistributionSetTagTest {
-
- private DistrubutionSetTagResource distrubutionSetTagResource;
-
- private static List assignedTargetRequestBodies;
-
- @BeforeClass
- public static void startupServer() {
- SpringApplication.run(Start.class, new String[0]);
- createTargetsAssignment();
- assignedTargetRequestBodies.add(new AssignedDistributionSetRequestBody().setDistributionSetId(100L));
- }
-
- @Before
- public void setup() {
- this.distrubutionSetTagResource = createDistrubutionSetTagResource();
- }
-
- // disabled as this runs not on CI environments.
- @Test
- @Description("Simple request of distrubutionset tag by ID")
- @Ignore
- public void getDistributionSetTag() {
- final TagsRest result = createDistributionSetTags(2);
-
- assertThat(distrubutionSetTagResource.getDistributionSetTag(result.get(0).getTagId()).getName()).isEqualTo(
- "Tag0");
-
- deleteDistributionSets(result);
- }
-
- // disabled as this runs not on CI environments.
- @Test
- @Description("Simple update of a distrubutionset tag")
- @Ignore
- public void updateDistributionSetTag() {
- final TagsRest created = createDistributionSetTags(10);
-
- distrubutionSetTagResource.updateDistributionSetTag(created.get(0).getTagId(), new TagRequestBodyPut()
- .setDescription("Test").setName("Test").setColour("Green"));
-
- final TagRest targetTag = distrubutionSetTagResource.getDistributionSetTag(created.get(0).getTagId());
- assertThat(targetTag.getName()).isEqualTo("Test");
- assertThat(targetTag.getDescription()).isEqualTo("Test");
- assertThat(targetTag.getColour()).isEqualTo("Green");
-
- deleteDistributionSets(created);
- }
-
- // disabled as this runs not on CI environments.
- @Test
- @Description("Simple request of all assigned distrubutionsets by a distrubutionset tag.")
- @Ignore
- public void getDistributionSetByTagId() {
- final TagsRest created = createDistributionSetTags(10);
- distrubutionSetTagResource.assignDistributionSets(created.get(2).getTagId(), assignedTargetRequestBodies);
-
- final DistributionSetsRest distributionSetsRest = distrubutionSetTagResource
- .getAssignedDistributionSets(created.get(2).getTagId());
- assertThat(distributionSetsRest).hasSize(5);
-
- distrubutionSetTagResource.unassignDistributionSets(created.get(2).getTagId());
- deleteDistributionSets(created);
- }
-
- @Test
- @Description("Toggle request to unassigned all assigned distrubutionset and assign all unassigned distrubutionset.")
- @Ignore
- public void toggleTagAssignment() {
- final TagsRest created = createDistributionSetTags(10);
- final Long id = created.get(2).getTagId();
-
- distrubutionSetTagResource.assignDistributionSets(id, assignedTargetRequestBodies);
- distrubutionSetTagResource.unassignDistributionSet(id, assignedTargetRequestBodies.get(0)
- .getDistributionSetId());
-
- DistributionSetTagAssigmentResultRest assigmentResultRest = distrubutionSetTagResource.toggleTagAssignment(id,
- assignedTargetRequestBodies);
-
- final TagRest targetTag = distrubutionSetTagResource.getDistributionSetTag(created.get(2).getTagId());
- assertThat(assigmentResultRest.getAssignedDistributionSets()).hasSize(1);
- assertThat(assigmentResultRest.getUnassignedDistributionSets()).hasSize(0);
-
- assigmentResultRest = distrubutionSetTagResource.toggleTagAssignment(id, assignedTargetRequestBodies);
- assertThat(assigmentResultRest.getAssignedDistributionSets()).hasSize(0);
- assertThat(assigmentResultRest.getUnassignedDistributionSets()).hasSize(5);
-
- distrubutionSetTagResource.unassignDistributionSets(targetTag.getTagId());
- deleteDistributionSets(created);
- }
-
- private void deleteDistributionSets(final List tags) {
- for (final TagRest tag : tags) {
- distrubutionSetTagResource.deleteDistributionSetTag(tag.getTagId());
- }
- }
-
- private TagsRest createDistributionSetTags(final int number) {
-
- final List tags = new ArrayList<>();
- for (int i = 0; i < number; i++) {
- tags.add(new TagRequestBodyPut().setDescription("Tag " + i).setName("Tag" + i).setColour("Red"));
- }
-
- final TagsRest result = distrubutionSetTagResource.createDistributionSetTags(tags);
-
- assertThat(result).hasSize(number);
- return result;
- }
-
- private DistrubutionSetTagResource createDistrubutionSetTagResource() {
- final DistrubutionSetTagResource distrubutionSetTagResource = Feign.builder().logger(new Logger.ErrorLogger())
- .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
- .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
- .target(DistrubutionSetTagResource.class, "http://localhost:8080");
- return distrubutionSetTagResource;
- }
-
- private static void createTargetsAssignment() {
-
- final List sets = new ArrayList<>();
- assignedTargetRequestBodies = new ArrayList<>();
- for (int i = 0; i < 5; i++) {
- final DistributionSetRequestBodyPost bodyPost = (DistributionSetRequestBodyPost) new DistributionSetRequestBodyPost()
- .setName("Ds" + i).setDescription("Ds" + i).setVersion("" + i);
- sets.add(bodyPost);
- }
-
- final DistributionSetsRest result = createDistributionSetResource().createDistributionSets(sets);
- for (final DistributionSetRest rest : result) {
- assignedTargetRequestBodies.add(new AssignedDistributionSetRequestBody().setDistributionSetId(rest
- .getDsId()));
- }
-
- }
-
- private static DistributionSetResource createDistributionSetResource() {
- final DistributionSetResource distributionSetResource = Feign.builder().logger(new Logger.ErrorLogger())
- .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
- .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
- .target(DistributionSetResource.class, "http://localhost:8080");
- return distributionSetResource;
- }
-
-}
diff --git a/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagTest.java b/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagTest.java
deleted file mode 100644
index 10f18b704..000000000
--- a/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTagTest.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.mgmt.api.client;
-
-import static org.fest.assertions.api.Assertions.assertThat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.hawkbit.app.Start;
-import org.eclipse.hawkbit.rest.resource.model.tag.AssignedTargetRequestBody;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
-import org.eclipse.hawkbit.rest.resource.model.tag.TargetTagAssigmentResultRest;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetRest;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.springframework.boot.SpringApplication;
-import org.springframework.context.annotation.Description;
-
-import ru.yandex.qatools.allure.annotations.Features;
-import ru.yandex.qatools.allure.annotations.Stories;
-import feign.Feign;
-import feign.Logger;
-import feign.auth.BasicAuthRequestInterceptor;
-import feign.jackson.JacksonDecoder;
-import feign.jackson.JacksonEncoder;
-
-@Features("Example Tests - Management RESTful API Client")
-@Stories("Target Tag Resource")
-public class TargetTagTest {
-
- private TargetTagResource targetTagResource;
-
- private static List assignedTargetRequestBodies;
-
- @BeforeClass
- public static void startupServer() {
- SpringApplication.run(Start.class, new String[0]);
- createTargetsAssignment();
- assignedTargetRequestBodies.add(new AssignedTargetRequestBody().setControllerId("NotExist"));
- }
-
- @Before
- public void setup() {
- this.targetTagResource = createTargetTagResource();
- }
-
- // disabled as this runs not on CI environments.
- @Test
- @Description("Simple request of target tag by ID")
- @Ignore
- public void getTargetTag() {
- final TagsRest result = createTargetTags(2);
-
- assertThat(targetTagResource.getTargetTag(result.get(0).getTagId()).getName()).isEqualTo("Tag0");
-
- deleteTargets(result);
- }
-
- // disabled as this runs not on CI environments.
- @Test
- @Description("Simple update of a target tag")
- @Ignore
- public void updateTargetTag() {
- final TagsRest created = createTargetTags(10);
-
- targetTagResource.updateTagretTag(created.get(0).getTagId(), new TagRequestBodyPut().setDescription("Test")
- .setName("Test").setColour("Green"));
-
- final TagRest targetTag = targetTagResource.getTargetTag(created.get(0).getTagId());
- assertThat(targetTag.getName()).isEqualTo("Test");
- assertThat(targetTag.getDescription()).isEqualTo("Test");
- assertThat(targetTag.getColour()).isEqualTo("Green");
-
- deleteTargets(created);
- }
-
- // disabled as this runs not on CI environments.
- @Test
- @Description("Simple request of all assigned targets by a target tag.")
- @Ignore
- public void getTargetsByTargetTagId() {
- final TagsRest created = createTargetTags(10);
- final Long tagId = created.get(2).getTagId();
- targetTagResource.assignTargets(tagId, assignedTargetRequestBodies);
-
- final TagRest targetTag = targetTagResource.getTargetTag(tagId);
- assertThat(targetTagResource.getAssignedTargets(tagId)).hasSize(5);
-
- targetTagResource.unassignTargets(targetTag.getTagId());
- deleteTargets(created);
- }
-
- @Test
- @Description("Toggle request to unassigned all assigned targets and assign all unassigned targets.")
- @Ignore
- public void toggleTagAssignment() {
- final TagsRest created = createTargetTags(10);
- final Long id = created.get(2).getTagId();
-
- targetTagResource.assignTargets(id, assignedTargetRequestBodies);
- targetTagResource.unassignTarget(id, assignedTargetRequestBodies.get(0).getControllerId());
-
- TargetTagAssigmentResultRest assigmentResultRest = targetTagResource.toggleTagAssignment(id,
- assignedTargetRequestBodies);
-
- final TagRest targetTag = targetTagResource.getTargetTag(created.get(2).getTagId());
- assertThat(assigmentResultRest.getAssignedTargets()).hasSize(1);
- assertThat(assigmentResultRest.getUnassignedTargets()).hasSize(0);
-
- assigmentResultRest = targetTagResource.toggleTagAssignment(id, assignedTargetRequestBodies);
- assertThat(assigmentResultRest.getAssignedTargets()).hasSize(0);
- assertThat(assigmentResultRest.getUnassignedTargets()).hasSize(5);
-
- targetTagResource.unassignTargets(targetTag.getTagId());
- deleteTargets(created);
- }
-
- private void deleteTargets(final List tags) {
- for (final TagRest tag : tags) {
- targetTagResource.deleteTargetTag(tag.getTagId());
- }
- }
-
- private TagsRest createTargetTags(final int number) {
-
- final List tags = new ArrayList<>();
- for (int i = 0; i < number; i++) {
- tags.add(new TagRequestBodyPut().setDescription("Tag " + i).setName("Tag" + i).setColour("Red"));
- }
-
- final TagsRest result = targetTagResource.createTargetTag(tags);
-
- assertThat(result).hasSize(number);
- return result;
- }
-
- private TargetTagResource createTargetTagResource() {
- final TargetTagResource targetResource = Feign.builder().logger(new Logger.ErrorLogger())
- .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
- .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
- .target(TargetTagResource.class, "http://localhost:8080");
- return targetResource;
- }
-
- private static void createTargetsAssignment() {
-
- final List targets = new ArrayList<>();
- assignedTargetRequestBodies = new ArrayList<>();
- for (int i = 0; i < 5; i++) {
-
- targets.add(new TargetRequestBody().setControllerId("test" + i).setName("testDevice"));
- }
-
- final TargetsRest result = createTargetResource().createTargets(targets);
- for (final TargetRest rest : result) {
- assignedTargetRequestBodies.add(new AssignedTargetRequestBody().setControllerId(rest.getControllerId()));
- }
-
- }
-
- private static TargetResource createTargetResource() {
- final TargetResource targetResource = Feign.builder().logger(new Logger.ErrorLogger())
- .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
- .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
- .target(TargetResource.class, "http://localhost:8080");
- return targetResource;
- }
-
-}
diff --git a/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTest.java b/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTest.java
deleted file mode 100644
index 745b119f6..000000000
--- a/examples/hawkbit-mgmt-api-client/src/test/java/org/eclipse/hawkbit/mgmt/api/client/TargetTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.mgmt.api.client;
-
-import static org.fest.assertions.api.Assertions.assertThat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.hawkbit.app.Start;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetPagedList;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetRest;
-import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.springframework.boot.SpringApplication;
-import org.springframework.context.annotation.Description;
-
-import feign.Feign;
-import feign.Logger;
-import feign.auth.BasicAuthRequestInterceptor;
-import feign.jackson.JacksonDecoder;
-import feign.jackson.JacksonEncoder;
-import ru.yandex.qatools.allure.annotations.Features;
-import ru.yandex.qatools.allure.annotations.Stories;
-
-@Features("Example Tests - Management RESTful API Client")
-@Stories("Target Resource")
-public class TargetTest {
-
- @BeforeClass
- public static void startupServer() {
- SpringApplication.run(Start.class, new String[0]);
- }
-
- // disabled as this runs not on CI environments.
- @Test
- @Description("Simple request of target by ID")
- @Ignore
- public void getTarget() {
- final TargetResource targetResource = createTargetResource();
- final TargetsRest result = createTargets(targetResource, 1);
-
- assertThat(targetResource.getTarget("test0").getName()).isEqualTo("testDevice");
-
- deleteTargets(targetResource, result);
- }
-
- // disabled as this runs not on CI environments.
- @Test
- @Description("Simple request of all targets with defined page sizing information (i.e. offset and limit).")
- @Ignore
- public void getTargetsAsPagedListWithDefinedPageSizing() {
- final TargetResource targetResource = createTargetResource();
- final TargetsRest created = createTargets(targetResource, 20);
-
- final TargetPagedList queryResult = targetResource.getTargets(0, 10);
-
- assertThat(queryResult.getContent()).hasSize(10);
- assertThat(queryResult.getTotal()).isEqualTo(20);
- assertThat(queryResult.getSize()).isEqualTo(10);
-
- deleteTargets(targetResource, created);
- }
-
- // disabled as this runs not on CI environments.
- @Test
- @Description("Simple request of all targets with defualt paging parameters.")
- @Ignore
- public void getTargetsAsPagedListWithDefaultPageSizing() {
- final TargetResource targetResource = createTargetResource();
- final TargetsRest created = createTargets(targetResource, 20);
-
- final TargetPagedList queryResult = targetResource.getTargets();
-
- assertThat(queryResult.getContent()).hasSize(20);
- assertThat(queryResult.getTotal()).isEqualTo(20);
- assertThat(queryResult.getSize()).isEqualTo(20);
-
- deleteTargets(targetResource, created);
- }
-
- private void deleteTargets(final TargetResource targetResource, final List targets) {
- for (final TargetRest targetRest : targets) {
- targetResource.deleteTarget(targetRest.getControllerId());
- }
- }
-
- private TargetsRest createTargets(final TargetResource targetResource, final int number) {
-
- final List targets = new ArrayList<>();
- for (int i = 0; i < number; i++) {
-
- targets.add(new TargetRequestBody().setControllerId("test" + i).setName("testDevice"));
- }
-
- final TargetsRest result = targetResource.createTargets(targets);
-
- assertThat(result).hasSize(number);
- return result;
- }
-
- private TargetResource createTargetResource() {
- final TargetResource targetResource = Feign.builder().logger(new Logger.ErrorLogger())
- .logLevel(Logger.Level.BASIC).decoder(new JacksonDecoder()).encoder(new JacksonEncoder())
- .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
- .target(TargetResource.class, "http://localhost:8080");
- return targetResource;
- }
-
-}
diff --git a/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/DistributionSetRestApi.java b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/DistributionSetRestApi.java
new file mode 100644
index 000000000..05d377950
--- /dev/null
+++ b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/DistributionSetRestApi.java
@@ -0,0 +1,365 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.eclipse.hawkbit.rest.resource.api;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.MetadataRest;
+import org.eclipse.hawkbit.rest.resource.model.MetadataRestPageList;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetPagedList;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRest;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.TargetAssignmentRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.TargetAssignmentResponseBody;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleAssigmentRest;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModulePagedList;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetPagedList;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * REST Resource handling for DistributionSet CRUD operations.
+ */
+@RequestMapping(RestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
+public interface DistributionSetRestApi {
+
+ /**
+ * Handles the GET request of retrieving all DistributionSets .
+ *
+ * @param pagingOffsetParam
+ * the offset of list of sets for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ * @return a list of all set for a defined or default page request with
+ * status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getDistributionSets(
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request of retrieving a single DistributionSet .
+ *
+ * @param distributionSetId
+ * the ID of the set to retrieve
+ *
+ * @return a single DistributionSet with status OK.
+ *
+ * @throws EntityNotFoundException
+ * in case no DistributionSet with the given ID exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getDistributionSet(
+ @PathVariable("distributionSetId") final Long distributionSetId);
+
+ /**
+ * Handles the POST request of creating new distribution sets . The request
+ * body must always be a list of sets.
+ *
+ * @param sets
+ * the DistributionSets to be created.
+ * @return In case all sets could successful created the ResponseEntity with
+ * status code 201 - Created but without ResponseBody. In any
+ * failure the JsonResponseExceptionHandler is handling the
+ * response.
+ */
+ @RequestMapping(method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE,
+ "application/hal+json" }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity createDistributionSets(
+ @RequestBody final List sets);
+
+ /**
+ * Handles the DELETE request for a single DistributionSet .
+ *
+ * @param distributionSetId
+ * the ID of the DistributionSet to delete
+ * @return status OK if delete as successful.
+ *
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetId}")
+ public ResponseEntity deleteDistributionSet(@PathVariable("distributionSetId") final Long distributionSetId);
+
+ /**
+ * Handles the UPDATE request for a single DistributionSet .
+ *
+ * @param distributionSetId
+ * the ID of the DistributionSet to delete
+ * @param toUpdate
+ * with the data that needs updating
+ *
+ * @return status OK if update as successful with updated content.
+ *
+ */
+ @RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetId}", consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity updateDistributionSet(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @RequestBody final DistributionSetRequestBodyPut toUpdate);
+
+ /**
+ * Handles the GET request of retrieving assigned targets to a specific
+ * distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set to retrieve the assigned
+ * targets
+ * @param pagingOffsetParam
+ * the offset of list of targets for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ * @return status OK if get request is successful with the paged list of
+ * targets
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/assignedTargets", produces = {
+ MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity getAssignedTargets(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request of retrieving installed targets to a specific
+ * distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set to retrieve the assigned
+ * targets
+ * @param pagingOffsetParam
+ * the offset of list of targets for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ * @return status OK if get request is successful with the paged list of
+ * targets
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/installedTargets", produces = {
+ MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity getInstalledTargets(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the POST request of assigning multiple targets to a single
+ * distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set within the URL path parameter
+ * @param targetIds
+ * the IDs of the target which should get assigned to the
+ * distribution set given in the response body
+ * @return status OK if the assignment of the targets was successful and a
+ * complex return body which contains information about the assigned
+ * targets and the already assigned targets counters
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetId}/assignedTargets", consumes = {
+ "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity createAssignedTarget(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @RequestBody final List targetIds);
+
+ /**
+ * Gets a paged list of meta data for a distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set for the meta data
+ * @param pagingOffsetParam
+ * the offset of list of targets for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=key==abc}
+ * @return status OK if get request is successful with the paged list of
+ * meta data
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/metadata", produces = {
+ MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity getMetadata(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Gets a single meta data value for a specific key of a distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set to get the meta data from
+ * @param metadataKey
+ * the key of the meta data entry to retrieve the value from
+ * @return status OK if get request is successful with the value of the meta
+ * data
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/metadata/{metadataKey}", produces = {
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getMetadataValue(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @PathVariable("metadataKey") final String metadataKey);
+
+ /**
+ * Updates a single meta data value of a distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set to update the meta data entry
+ * @param metadataKey
+ * the key of the meta data to update the value
+ * @return status OK if the update request is successful and the updated
+ * meta data result
+ */
+ @RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetId}/metadata/{metadataKey}", produces = {
+ MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity updateMetadata(@PathVariable("distributionSetId") final Long distributionSetId,
+ @PathVariable("metadataKey") final String metadataKey, @RequestBody final MetadataRest metadata);
+
+ /**
+ * Deletes a single meta data entry from the distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set to delete the meta data entry
+ * @param metadataKey
+ * the key of the meta data to delete
+ * @return status OK if the delete request is successful
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetId}/metadata/{metadataKey}")
+ public ResponseEntity deleteMetadata(@PathVariable("distributionSetId") final Long distributionSetId,
+ @PathVariable("metadataKey") final String metadataKey);
+
+ /**
+ * Creates a list of meta data for a specific distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set to create meta data for
+ * @param metadataRest
+ * the list of meta data entries to create
+ * @return status created if post request is successful with the value of
+ * the created meta data
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetId}/metadata", consumes = {
+ MediaType.APPLICATION_JSON_VALUE,
+ "application/hal+json" }, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity> createMetadata(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @RequestBody final List metadataRest);
+
+ /**
+ * Assigns a list of software modules to a distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set to assign software modules for
+ * @param softwareModuleIDs
+ * the list of software modules ids to assign
+ * @return http status
+ *
+ * @throws EntityNotFoundException
+ * in case no distribution set with the given
+ * {@code distributionSetId} exists.
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetId}/assignedSM", consumes = {
+ MediaType.APPLICATION_JSON_VALUE,
+ "application/hal+json" }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity assignSoftwareModules(@PathVariable("distributionSetId") final Long distributionSetId,
+ @RequestBody final List softwareModuleIDs);
+
+ /**
+ * Deletes the assignment of the software module form the distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution set to reject the software module
+ * for
+ * @param softwareModuleId
+ * the software module id to get rejected form the distribution
+ * set
+ * @return status OK if rejection was successful.
+ * @throws EntityNotFoundException
+ * in case no distribution set with the given
+ * {@code distributionSetId} exists.
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetId}/assignedSM/{softwareModuleId}")
+ public ResponseEntity deleteAssignSoftwareModules(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @PathVariable("softwareModuleId") final Long softwareModuleId);
+
+ /**
+ * Handles the GET request for retrieving the assigned software modules of a
+ * specific distribution set.
+ *
+ * @param distributionSetId
+ * the ID of the distribution to retrieve
+ * @param pagingOffsetParam
+ * the offset of list of sets for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @return a list of the assigned software modules of a distribution set
+ * with status OK, if none is assigned than {@code null}
+ * @throws EntityNotFoundException
+ * in case no distribution set with the given
+ * {@code distributionSetId} exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/assignedSM", produces = {
+ "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getAssignedSoftwareModules(
+ @PathVariable("distributionSetId") final Long distributionSetId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam);
+}
diff --git a/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/DistributionSetTagRestApi.java b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/DistributionSetTagRestApi.java
new file mode 100644
index 000000000..d99368dc2
--- /dev/null
+++ b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/DistributionSetTagRestApi.java
@@ -0,0 +1,215 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.resource.api;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.AssignedDistributionSetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.tag.DistributionSetTagAssigmentResultRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagPagedList;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * REST Resource handling for DistributionSetTag CRUD operations.
+ *
+ */
+@RequestMapping(RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING)
+public interface DistributionSetTagRestApi {
+ /**
+ * Handles the GET request of retrieving all DistributionSet tags.
+ *
+ * @param pagingOffsetParam
+ * the offset of list of DistributionSet tags for pagination,
+ * might not be present in the rest request then default value
+ * will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ * @return a list of all target tags for a defined or default page request
+ * with status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getDistributionSetTags(
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request of retrieving a single distribution set tag.
+ *
+ * @param distributionsetTagId
+ * the ID of the distribution set tag to retrieve
+ *
+ * @return a single distribution set tag with status OK.
+ * @throws EntityNotFoundException
+ * in case the given {@code distributionsetTagId} doesn't
+ * exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionsetTagId}", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getDistributionSetTag(
+ @PathVariable("distributionsetTagId") final Long distributionsetTagId);
+
+ /**
+ * Handles the POST request of creating new distribution set tag. The
+ * request body must always be a list of tags.
+ *
+ * @param tags
+ * the distribution set tags to be created.
+ * @return In case all modules could successful created the ResponseEntity
+ * with status code 201 - Created. The Response Body are the created
+ * distribution set tags but without ResponseBody.
+ */
+ @RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity createDistributionSetTags(@RequestBody final List tags);
+
+ /**
+ *
+ * Handles the PUT request of updating a single distribution set tag.
+ *
+ * @param distributionsetTagId
+ * the ID of the distribution set tag
+ * @param restDSTagRest
+ * the the request body to be updated
+ * @return status OK if update is successful and the updated distribution
+ * set tag.
+ * @throws EntityNotFoundException
+ * in case the given {@code distributionsetTagId} doesn't
+ * exists.
+ */
+ @RequestMapping(method = RequestMethod.PUT, value = "/{distributionsetTagId}", consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity updateDistributionSetTag(
+ @PathVariable("distributionsetTagId") final Long distributionsetTagId,
+ @RequestBody final TagRequestBodyPut restDSTagRest);
+
+ /**
+ * Handles the DELETE request for a single distribution set tag.
+ *
+ * @param distributionsetTagId
+ * the ID of the distribution set tag
+ * @return status OK if delete as successfully.
+ * @throws EntityNotFoundException
+ * in case the given {@code distributionsetTagId} doesn't
+ * exists.
+ *
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionsetTagId}")
+ public ResponseEntity deleteDistributionSetTag(
+ @PathVariable("distributionsetTagId") final Long distributionsetTagId);
+
+ /**
+ * Handles the GET request of retrieving all assigned distribution sets by
+ * the given tag id.
+ *
+ * @param distributionsetTagId
+ * the ID of the distribution set tag
+ *
+ * @return the list of assigned distribution sets.
+ * @throws EntityNotFoundException
+ * in case the given {@code distributionsetTagId} doesn't
+ * exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
+ public ResponseEntity getAssignedDistributionSets(
+ @PathVariable("distributionsetTagId") final Long distributionsetTagId);
+
+ /**
+ * Handles the POST request to toggle the assignment of distribution sets by
+ * the given tag id.
+ *
+ * @param distributionsetTagIds
+ * the ID of the distribution set tag to retrieve
+ * @param assignedDSRequestBodies
+ * list of distribution set ids to be toggled
+ *
+ * @return the list of assigned distribution sets and unassigned
+ * distribution sets.
+ * @throws EntityNotFoundException
+ * in case the given {@code distributionsetTagId} doesn't
+ * exists.
+ */
+ @RequestMapping(method = RequestMethod.POST, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING
+ + "/toggleTagAssignment")
+ public ResponseEntity toggleTagAssignment(
+ @PathVariable("distributionsetTagId") final Long distributionsetTagId,
+ @RequestBody final List assignedDSRequestBodies);
+
+ /**
+ * Handles the POST request to assign distribution sets to the given tag id.
+ *
+ * @param distributionsetTagId
+ * the ID of the distribution set tag to retrieve
+ * @param assignedDSRequestBodies
+ * list of distribution sets ids to be assigned
+ *
+ * @return the list of assigned distribution set.
+ * @throws EntityNotFoundException
+ * in case the given {@code distributionsetTagId} doesn't
+ * exists.
+ */
+ @RequestMapping(method = RequestMethod.POST, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
+ public ResponseEntity assignDistributionSets(
+ @PathVariable("distributionsetTagId") final Long distributionsetTagId,
+ @RequestBody final List assignedDSRequestBodies);
+
+ /**
+ * Handles the DELETE request to unassign all distribution set from the
+ * given tag id.
+ *
+ * @param distributionsetTagId
+ * the ID of the distribution set tag to retrieve
+ * @return http status code
+ * @throws EntityNotFoundException
+ * in case the given {@code distributionsetTagId} doesn't
+ * exists.
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
+ public ResponseEntity unassignDistributionSets(
+ @PathVariable("distributionsetTagId") final Long distributionsetTagId);
+
+ /**
+ * Handles the DELETE request to unassign one distribution set from the
+ * given tag id.
+ *
+ * @param distributionsetTagId
+ * the ID of the distribution set tag
+ * @param distributionsetId
+ * the ID of the distribution set to unassign
+ * @return http status code
+ * @throws EntityNotFoundException
+ * in case the given {@code distributionsetTagId} doesn't
+ * exists.
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING
+ + "/{distributionsetId}")
+ public ResponseEntity unassignDistributionSet(
+ @PathVariable("distributionsetTagId") final Long distributionsetTagId,
+ @PathVariable("distributionsetId") final Long distributionsetId);
+}
diff --git a/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/DistributionSetTypeRestApi.java b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/DistributionSetTypeRestApi.java
new file mode 100644
index 000000000..9bed7f4f8
--- /dev/null
+++ b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/DistributionSetTypeRestApi.java
@@ -0,0 +1,259 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.resource.api;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.IdRest;
+import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypePagedList;
+import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRest;
+import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypesRest;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRest;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypesRest;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * REST Resource handling for SoftwareModule and related Artifact CRUD
+ * operations.
+ *
+ */
+@RequestMapping(RestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING)
+public interface DistributionSetTypeRestApi {
+
+ /**
+ * Handles the GET request of retrieving all DistributionSetTypes.
+ *
+ * @param pagingOffsetParam
+ * the offset of list of modules for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ *
+ * @return a list of all DistributionSetType for a defined or default page
+ * request with status OK. The response is always paged. In any
+ * failure the JsonResponseExceptionHandler is handling the
+ * response.
+ */
+ @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getDistributionSetTypes(
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request of retrieving a single DistributionSetType
+ * within.
+ *
+ * @param distributionSetTypeId
+ * the ID of the module type to retrieve
+ *
+ * @return a single softwareModule with status OK.
+ * @throws EntityNotFoundException
+ * in case no with the given {@code softwareModuleId} exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getDistributionSetType(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId);
+
+ /**
+ * Handles the DELETE request for a single Distribution Set Type.
+ *
+ * @param distributionSetTypeId
+ * the ID of the module to retrieve
+ * @return status OK if delete as sucessfull.
+ *
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetTypeId}")
+ public ResponseEntity deleteDistributionSetType(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId);
+
+ /**
+ * Handles the PUT request of updating a Distribution Set Type.
+ *
+ * @param distributionSetTypeId
+ * the ID of the software module in the URL
+ * @param restDistributionSetType
+ * the module type to be updated.
+ * @return status OK if update is successful
+ */
+ @RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetTypeId}", consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity updateDistributionSetType(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId,
+ @RequestBody final DistributionSetTypeRequestBodyPut restDistributionSetType);
+
+ /**
+ * Handles the POST request of creating new DistributionSetTypes. The
+ * request body must always be a list of types.
+ *
+ * @param distributionSetTypes
+ * the modules to be created.
+ * @return In case all modules could successful created the ResponseEntity
+ * with status code 201 - Created but without ResponseBody. In any
+ * failure the JsonResponseExceptionHandler is handling the
+ * response.
+ */
+ @RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity createDistributionSetTypes(
+ @RequestBody final List distributionSetTypes);
+
+ /**
+ * Handles the GET request of retrieving the list of mandatory software
+ * module types in that distribution set type.
+ *
+ * @param distributionSetTypeId
+ * of the DistributionSetType.
+ * @return Unpaged list of module types and OK in case of success.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
+ + RestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES, produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getMandatoryModules(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId);
+
+ /**
+ * Handles the GET request of retrieving the single mandatory software
+ * module type in that distribution set type.
+ *
+ * @param distributionSetTypeId
+ * of the DistributionSetType.
+ * @param softwareModuleTypeId
+ * of SoftwareModuleType.
+ * @return Unpaged list of module types and OK in case of success.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
+ + RestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES
+ + "/{softwareModuleTypeId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getMandatoryModule(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId,
+ @PathVariable("softwareModuleTypeId") final Long softwareModuleTypeId);
+
+ /**
+ * Handles the GET request of retrieving the single optional software module
+ * type in that distribution set type.
+ *
+ * @param distributionSetTypeId
+ * of the DistributionSetType.
+ * @param softwareModuleTypeId
+ * of SoftwareModuleType.
+ * @return Unpaged list of module types and OK in case of success.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
+ + RestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES
+ + "/{softwareModuleTypeId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getOptionalModule(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId,
+ @PathVariable("softwareModuleTypeId") final Long softwareModuleTypeId);
+
+ /**
+ * Handles the GET request of retrieving the list of optional software
+ * module types in that distribution set type.
+ *
+ * @param distributionSetTypeId
+ * of the DistributionSetType.
+ * @return Unpaged list of module types and OK in case of success.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
+ + RestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES, produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getOptionalModules(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId);
+
+ /**
+ * Handles DELETE request for removing a mandatory module from the
+ * DistributionSetType.
+ *
+ * @param distributionSetTypeId
+ * of the DistributionSetType.
+ * @param softwareModuleTypeId
+ * of the SoftwareModuleType to remove
+ *
+ * @return OK if the request was successful
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetTypeId}/"
+ + RestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES
+ + "/{softwareModuleTypeId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity removeMandatoryModule(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId,
+ @PathVariable("softwareModuleTypeId") final Long softwareModuleTypeId);
+
+ /**
+ * Handles DELETE request for removing an optional module from the
+ * DistributionSetType.
+ *
+ * @param distributionSetTypeId
+ * of the DistributionSetType.
+ * @param softwareModuleTypeId
+ * of the SoftwareModuleType to remove
+ *
+ * @return OK if the request was successful
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetTypeId}/"
+ + RestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES
+ + "/{softwareModuleTypeId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity removeOptionalModule(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId,
+ @PathVariable("softwareModuleTypeId") final Long softwareModuleTypeId);
+
+ /**
+ * Handles the POST request for adding a mandatory software module type to a
+ * distribution set type.
+ *
+ * @param distributionSetTypeId
+ * of the DistributionSetType.
+ * @param smtId
+ * of the SoftwareModuleType to add
+ *
+ * @return OK if the request was successful
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetTypeId}/"
+ + RestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES, consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity addMandatoryModule(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId, @RequestBody final IdRest smtId);
+
+ /**
+ * Handles the POST request for adding an optional software module type to a
+ * distribution set type.
+ *
+ * @param distributionSetTypeId
+ * of the DistributionSetType.
+ * @param smtId
+ * of the SoftwareModuleType to add
+ *
+ * @return OK if the request was successful
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetTypeId}/"
+ + RestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES, consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity addOptionalModule(
+ @PathVariable("distributionSetTypeId") final Long distributionSetTypeId, @RequestBody final IdRest smtId);
+
+}
diff --git a/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/RolloutRestApi.java b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/RolloutRestApi.java
new file mode 100644
index 000000000..fe1c7caa5
--- /dev/null
+++ b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/RolloutRestApi.java
@@ -0,0 +1,209 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.resource.api;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutPagedList;
+import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutResponseBody;
+import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutRestRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.rolloutgroup.RolloutGroupPagedList;
+import org.eclipse.hawkbit.rest.resource.model.rolloutgroup.RolloutGroupResponseBody;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetPagedList;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * REST Resource handling rollout CRUD operations.
+ *
+ */
+@RequestMapping(RestConstants.ROLLOUT_V1_REQUEST_MAPPING)
+public interface RolloutRestApi {
+
+ /**
+ * Handles the GET request of retrieving all rollouts.
+ *
+ * @param pagingOffsetParam
+ * the offset of list of rollouts for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ * @return a list of all rollouts for a defined or default page request with
+ * status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity getRollouts(
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request of retrieving a single rollout.
+ *
+ * @param rolloutId
+ * the ID of the rollout to retrieve
+ * @return a single rollout with status OK.
+ * @throws EntityNotFoundException
+ * in case no rollout with the given {@code rolloutId} exists.
+ */
+ @RequestMapping(value = "/{rolloutId}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE,
+ "application/hal+json" })
+ public ResponseEntity getRollout(@PathVariable("rolloutId") final Long rolloutId);
+
+ /**
+ * Handles the POST request for creating rollout.
+ *
+ * @param rollout
+ * the rollout body to be created.
+ * @return In case rollout could successful created the ResponseEntity with
+ * status code 201 with the successfully created rollout. In any
+ * failure the JsonResponseExceptionHandler is handling the
+ * response.
+ * @throws EntityNotFoundException
+ */
+ @RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity create(@RequestBody final RolloutRestRequestBody rolloutRequestBody);
+
+ /**
+ * Handles the POST request for starting a rollout.
+ *
+ * @param rolloutId
+ * the ID of the rollout to be started.
+ * @return OK response (200) if rollout could be started. In case of any
+ * exception the corresponding errors occur.
+ * @throws EntityNotFoundException
+ * @see RolloutManagement#startRollout(Rollout)
+ * @see ResponseExceptionHandler
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{rolloutId}/start", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity start(@PathVariable("rolloutId") final Long rolloutId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_ASYNC, defaultValue = "false") final boolean startAsync);
+
+ /**
+ * Handles the POST request for pausing a rollout.
+ *
+ * @param rolloutId
+ * the ID of the rollout to be paused.
+ * @return OK response (200) if rollout could be paused. In case of any
+ * exception the corresponding errors occur.
+ * @throws EntityNotFoundException
+ * @see RolloutManagement#pauseRollout(Rollout)
+ * @see ResponseExceptionHandler
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{rolloutId}/pause", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity pause(@PathVariable("rolloutId") final Long rolloutId);
+
+ /**
+ * Handles the POST request for resuming a rollout.
+ *
+ * @param rolloutId
+ * the ID of the rollout to be resumed.
+ * @return OK response (200) if rollout could be resumed. In case of any
+ * exception the corresponding errors occur.
+ * @throws EntityNotFoundException
+ * @see RolloutManagement#resumeRollout(Rollout)
+ * @see ResponseExceptionHandler
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{rolloutId}/resume", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity resume(@PathVariable("rolloutId") final Long rolloutId);
+
+ /**
+ * Handles the GET request of retrieving all rollout groups referred to a
+ * rollout.
+ *
+ * @param pagingOffsetParam
+ * the offset of list of rollout groups for pagination, might not
+ * be present in the rest request then default value will be
+ * applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ * @return a list of all rollout groups referred to a rollout for a defined
+ * or default page request with status OK. The response is always
+ * paged. In any failure the JsonResponseExceptionHandler is
+ * handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{rolloutId}/deploygroups", produces = {
+ MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity getRolloutGroups(@PathVariable("rolloutId") final Long rolloutId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request for retrieving a single rollout group.
+ *
+ * @param rolloutId
+ * the rolloutId to retrieve the group from
+ * @param groupId
+ * the groupId to retrieve the rollout group
+ * @return the OK response containing the RolloutGroupResponseBody
+ * @throws EntityNotFoundException
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{rolloutId}/deploygroups/{groupId}", produces = {
+ MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity getRolloutGroup(@PathVariable("rolloutId") final Long rolloutId,
+ @PathVariable("groupId") final Long groupId);
+
+ /**
+ * Retrieves all targets related to a specific rollout group.
+ *
+ * @param rolloutId
+ * the ID of the rollout
+ * @param groupId
+ * the ID of the rollout group
+ * @param pagingOffsetParam
+ * the offset of list of rollout groups for pagination, might not
+ * be present in the rest request then default value will be
+ * applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ * @return a paged list of targets related to a specific rollout and rollout
+ * group.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{rolloutId}/deploygroups/{groupId}/targets", produces = {
+ MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity getRolloutGroupTargets(@PathVariable("rolloutId") final Long rolloutId,
+ @PathVariable("groupId") final Long groupId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+}
diff --git a/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/SoftwareModuleRestAPI.java b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/SoftwareModuleRestAPI.java
new file mode 100644
index 000000000..0662c43ba
--- /dev/null
+++ b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/SoftwareModuleRestAPI.java
@@ -0,0 +1,289 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.resource.api;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.MetadataRest;
+import org.eclipse.hawkbit.rest.resource.model.MetadataRestPageList;
+import org.eclipse.hawkbit.rest.resource.model.artifact.ArtifactRest;
+import org.eclipse.hawkbit.rest.resource.model.artifact.ArtifactsRest;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModulePagedList;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRest;
+import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModulesRest;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * REST Resource handling for SoftwareModule and related Artifact CRUD
+ * operations.
+ *
+ */
+@RequestMapping(RestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING)
+public interface SoftwareModuleRestAPI {
+
+ /**
+ * Handles POST request for artifact upload.
+ *
+ * @param softwareModuleId
+ * of the parent SoftwareModule
+ * @param file
+ * that has to be uploaded
+ * @param optionalFileName
+ * to override {@link MultipartFile#getOriginalFilename()}
+ * @param md5Sum
+ * checksum for uploaded content check
+ * @param sha1Sum
+ * checksum for uploaded content check
+ *
+ * @return In case all sets could successful be created the ResponseEntity
+ * with status code 201 - Created but without ResponseBody. In any
+ * failure the JsonResponseExceptionHandler is handling the
+ * response.
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/artifacts", produces = {
+ "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity uploadArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ @RequestParam("file") final MultipartFile file,
+ @RequestParam(value = "filename", required = false) final String optionalFileName,
+ @RequestParam(value = "md5sum", required = false) final String md5Sum,
+ @RequestParam(value = "sha1sum", required = false) final String sha1Sum);
+
+ /**
+ * Handles the GET request of retrieving all meta data of artifacts assigned
+ * to a software module.
+ *
+ * @param softwareModuleId
+ * of the parent SoftwareModule
+ *
+ * @return a list of all artifacts for a defined or default page request
+ * with status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/artifacts", produces = {
+ "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ @ResponseBody
+ public ResponseEntity getArtifacts(@PathVariable("softwareModuleId") final Long softwareModuleId);
+
+ /**
+ * Handles the GET request of retrieving a single Artifact meta data
+ * request.
+ *
+ * @param softwareModuleId
+ * of the parent SoftwareModule
+ * @param artifactId
+ * of the related LocalArtifact
+ *
+ * @return responseEntity with status ok if successful
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/artifacts/{artifactId}", produces = {
+ "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ @ResponseBody
+ public ResponseEntity getArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ @PathVariable("artifactId") final Long artifactId);
+
+ /**
+ * Handles the DELETE request for a single SoftwareModule.
+ *
+ * @param softwareModuleId
+ * the ID of the module that has the artifact
+ * @param artifactId
+ * of the artifact to be deleted
+ *
+ * @return status OK if delete as successful.
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{softwareModuleId}/artifacts/{artifactId}")
+ @ResponseBody
+ public ResponseEntity deleteArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ @PathVariable("artifactId") final Long artifactId);
+
+ /**
+ * Handles the GET request of retrieving all softwaremodules.
+ *
+ * @param pagingOffsetParam
+ * the offset of list of modules for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ *
+ * @return a list of all modules for a defined or default page request with
+ * status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getSoftwareModules(
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request of retrieving a single software module.
+ *
+ * @param softwareModuleId
+ * the ID of the module to retrieve
+ *
+ * @return a single softwareModule with status OK.
+ * @throws EntityNotFoundException
+ * in case no with the given {@code softwareModuleId} exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getSoftwareModule(
+ @PathVariable("softwareModuleId") final Long softwareModuleId);
+
+ /**
+ * Handles the POST request of creating new softwaremodules. The request
+ * body must always be a list of modules.
+ *
+ * @param softwareModules
+ * the modules to be created.
+ * @return In case all modules could successful created the ResponseEntity
+ * with status code 201 - Created but without ResponseBody. In any
+ * failure the JsonResponseExceptionHandler is handling the
+ * response.
+ */
+ @RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity createSoftwareModules(
+ @RequestBody final List softwareModules);
+
+ /**
+ * Handles the PUT request of updating a software module.
+ *
+ * @param softwareModuleId
+ * the ID of the software module in the URL
+ * @param restSoftwareModule
+ * the modules to be updated.
+ * @return status OK if update is successful
+ */
+ @RequestMapping(method = RequestMethod.PUT, value = "/{softwareModuleId}", consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity updateSoftwareModule(
+ @PathVariable("softwareModuleId") final Long softwareModuleId,
+ @RequestBody final SoftwareModuleRequestBodyPut restSoftwareModule);
+
+ /**
+ * Handles the DELETE request for a single softwaremodule.
+ *
+ * @param softwareModuleId
+ * the ID of the module to retrieve
+ * @return status OK if delete as sucessfull.
+ *
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{softwareModuleId}")
+ public ResponseEntity deleteSoftwareModule(@PathVariable("softwareModuleId") final Long softwareModuleId);
+
+ /**
+ * Gets a paged list of meta data for a software module.
+ *
+ * @param softwareModuleId
+ * the ID of the software module for the meta data
+ * @param pagingOffsetParam
+ * the offset of list of meta data for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=key==abc}
+ * @return status OK if get request is successful with the paged list of
+ * meta data
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata", produces = {
+ MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity getMetadata(
+ @PathVariable("softwareModuleId") final Long softwareModuleId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Gets a single meta data value for a specific key of a software module.
+ *
+ * @param softwareModuleId
+ * the ID of the software module to get the meta data from
+ * @param metadataKey
+ * the key of the meta data entry to retrieve the value from
+ * @return status OK if get request is successful with the value of the meta
+ * data
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = {
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getMetadataValue(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ @PathVariable("metadataKey") final String metadataKey);
+
+ /**
+ * Updates a single meta data value of a software module.
+ *
+ * @param softwareModuleId
+ * the ID of the software module to update the meta data entry
+ * @param metadataKey
+ * the key of the meta data to update the value
+ * @return status OK if the update request is successful and the updated
+ * meta data result
+ */
+ @RequestMapping(method = RequestMethod.PUT, value = "/{softwareModuleId}/metadata/{metadataKey}", produces = {
+ MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity updateMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ @PathVariable("metadataKey") final String metadataKey, @RequestBody final MetadataRest metadata);
+
+ /**
+ * Deletes a single meta data entry from the software module.
+ *
+ * @param softwareModuleId
+ * the ID of the software module to delete the meta data entry
+ * @param metadataKey
+ * the key of the meta data to delete
+ * @return status OK if the delete request is successful
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{softwareModuleId}/metadata/{metadataKey}")
+ public ResponseEntity deleteMetadata(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ @PathVariable("metadataKey") final String metadataKey);
+
+ /**
+ * Creates a list of meta data for a specific software module.
+ *
+ * @param softwareModuleId
+ * the ID of the distribution set to create meta data for
+ * @param metadataRest
+ * the list of meta data entries to create
+ * @return status created if post request is successful with the value of
+ * the created meta data
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/metadata", consumes = {
+ MediaType.APPLICATION_JSON_VALUE,
+ "application/hal+json" }, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
+ public ResponseEntity> createMetadata(
+ @PathVariable("softwareModuleId") final Long softwareModuleId,
+ @RequestBody final List metadataRest);
+
+}
diff --git a/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/SoftwareModuleTypeRestApi.java b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/SoftwareModuleTypeRestApi.java
new file mode 100644
index 000000000..0c4756a04
--- /dev/null
+++ b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/SoftwareModuleTypeRestApi.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.resource.api;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypePagedList;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRequestBodyPost;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRest;
+import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypesRest;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * REST Resource handling for SoftwareModule and related Artifact CRUD
+ * operations.
+ *
+ */
+@RequestMapping(RestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING)
+public interface SoftwareModuleTypeRestApi {
+ /**
+ * Handles the GET request of retrieving all SoftwareModuleTypes .
+ *
+ * @param pagingOffsetParam
+ * the offset of list of modules for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ *
+ * @return a list of all module type for a defined or default page request
+ * with status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getTypes(
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request of retrieving a single software module type .
+ *
+ * @param softwareModuleTypeId
+ * the ID of the module type to retrieve
+ *
+ * @return a single softwareModule with status OK.
+ * @throws EntityNotFoundException
+ * in case no with the given {@code softwareModuleId} exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleTypeId}", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getSoftwareModuleType(
+ @PathVariable("softwareModuleTypeId") final Long softwareModuleTypeId);
+
+ /**
+ * Handles the DELETE request for a single software module type .
+ *
+ * @param softwareModuleTypeId
+ * the ID of the module to retrieve
+ * @return status OK if delete as successfully.
+ *
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{softwareModuleTypeId}")
+ public ResponseEntity deleteSoftwareModuleType(
+ @PathVariable("softwareModuleTypeId") final Long softwareModuleTypeId);
+
+ /**
+ * Handles the PUT request of updating a software module type .
+ *
+ * @param softwareModuleTypeId
+ * the ID of the software module in the URL
+ * @param restSoftwareModuleType
+ * the module type to be updated.
+ * @return status OK if update is successful
+ */
+ @RequestMapping(method = RequestMethod.PUT, value = "/{softwareModuleTypeId}", consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity updateSoftwareModuleType(
+ @PathVariable("softwareModuleTypeId") final Long softwareModuleTypeId,
+ @RequestBody final SoftwareModuleTypeRequestBodyPut restSoftwareModuleType);
+
+ /**
+ * Handles the POST request of creating new SoftwareModuleTypes. The request
+ * body must always be a list of types.
+ *
+ * @param softwareModuleTypes
+ * the modules to be created.
+ * @return In case all modules could successful created the ResponseEntity
+ * with status code 201 - Created but without ResponseBody. In any
+ * failure the JsonResponseExceptionHandler is handling the
+ * response.
+ */
+ @RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity createSoftwareModuleTypes(
+ @RequestBody final List softwareModuleTypes);
+
+}
diff --git a/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/TargetRestApi.java b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/TargetRestApi.java
new file mode 100644
index 000000000..9d63a520f
--- /dev/null
+++ b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/TargetRestApi.java
@@ -0,0 +1,284 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.resource.api;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.action.ActionPagedList;
+import org.eclipse.hawkbit.rest.resource.model.action.ActionRest;
+import org.eclipse.hawkbit.rest.resource.model.action.ActionStatusPagedList;
+import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRest;
+import org.eclipse.hawkbit.rest.resource.model.target.DistributionSetAssigmentRest;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetAttributes;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetPagedList;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetRest;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * Api for handling target operations.
+ */
+@RequestMapping(RestConstants.TARGET_V1_REQUEST_MAPPING)
+public interface TargetRestApi {
+
+ /**
+ * Handles the GET request of retrieving a single target.
+ *
+ * @param targetId
+ * the ID of the target to retrieve
+ * @return a single target with status OK.
+ * @throws EntityNotFoundException
+ * in case no target with the given {@code targetId} exists.
+ */
+
+ @RequestMapping(method = RequestMethod.GET, value = "/{targetId}", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getTarget(@PathVariable("targetId") final String targetId);
+
+ /**
+ * Handles the GET request of retrieving all targets.
+ *
+ * @param pagingOffsetParam
+ * the offset of list of targets for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ * @return a list of all targets for a defined or default page request with
+ * status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+
+ @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getTargets(
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the POST request of creating new targets. The request body must
+ * always be a list of targets.
+ *
+ * @param targets
+ * the targets to be created.
+ * @return In case all targets could successful created the ResponseEntity
+ * with status code 201 with a list of successfully created
+ * entities. In any failure the JsonResponseExceptionHandler is
+ * handling the response.
+ */
+ @RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity createTargets(@RequestBody final List targets);
+
+ /**
+ * Handles the PUT request of updating a target. The ID is within the URL
+ * path of the request. A given ID in the request body is ignored. It's not
+ * possible to set fields to {@code null} values.
+ *
+ * @param targetId
+ * the path parameter which contains the ID of the target
+ * @param targetRest
+ * the request body which contains the fields which should be
+ * updated, fields which are not given are ignored for the
+ * udpate.
+ * @return the updated target response which contains all fields also fields
+ * which have not updated
+ */
+ @RequestMapping(method = RequestMethod.PUT, value = "/{targetId}", consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity updateTarget(@PathVariable("targetId") final String targetId,
+ @RequestBody final TargetRequestBody targetRest);
+
+ /**
+ * Handles the DELETE request of deleting a target.
+ *
+ * @param targetId
+ * the ID of the target to be deleted
+ * @return If the given targetId could exists and could be deleted Http OK.
+ * In any failure the JsonResponseExceptionHandler is handling the
+ * response.
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{targetId}", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity deleteTarget(@PathVariable("targetId") final String targetId);
+
+ /**
+ * Handles the GET request of retrieving the attributes of a specific
+ * target.
+ *
+ * @param targetId
+ * the ID of the target to retrieve the attributes.
+ * @return the target attributes as map response with status OK
+ * @throws EntityNotFoundException
+ * in case no target with the given {@code targetId} exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/attributes", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getAttributes(@PathVariable("targetId") final String targetId);
+
+ /**
+ * Handles the GET request of retrieving the Actions of a specific target.
+ *
+ * @param targetId
+ * to load actions for
+ * @param pagingOffsetParam
+ * the offset of list of targets for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=status==pending}
+ * @return a list of all Actions for a defined or default page request with
+ * status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/actions", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getActionHistory(@PathVariable("targetId") final String targetId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request of retrieving a specific Actions of a specific
+ * Target.
+ *
+ * @param targetId
+ * to load the action for
+ * @param actionId
+ * to load
+ * @return the action
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/actions/{actionId}", produces = {
+ "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getAction(@PathVariable("targetId") final String targetId,
+ @PathVariable("actionId") final Long actionId);
+
+ /**
+ * Handles the DELETE request of canceling an specific Actions of a specific
+ * Target.
+ *
+ * @param targetId
+ * the ID of the target in the URL path parameter
+ * @param actionId
+ * the ID of the action in the URL path parameter
+ * @param force
+ * optional parameter, which indicates a force cancel
+ * @return status no content in case cancellation was successful
+ * @throws CancelActionNotAllowedException
+ * if the given action is not active and cannot be canceled.
+ * @throws EntityNotFoundException
+ * if the target or the action is not found
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{targetId}/actions/{actionId}")
+ public ResponseEntity cancelAction(@PathVariable("targetId") final String targetId,
+ @PathVariable("actionId") final Long actionId,
+ @RequestParam(value = "force", required = false, defaultValue = "false") final boolean force);
+
+ /**
+ * Handles the GET request of retrieving the ActionStatus of a specific
+ * target and action.
+ *
+ * @param targetId
+ * of the the action
+ * @param actionId
+ * of the status we are intend to load
+ * @param pagingOffsetParam
+ * the offset of list of targets for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @return a list of all ActionStatus for a defined or default page request
+ * with status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/actions/{actionId}/status", produces = {
+ "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getActionStatusList(@PathVariable("targetId") final String targetId,
+ @PathVariable("actionId") final Long actionId,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam);
+
+ /**
+ * Handles the GET request of retrieving the assigned distribution set of an
+ * specific target.
+ *
+ * @param targetId
+ * the ID of the target to retrieve the assigned distribution
+ * @return the assigned distribution set with status OK, if none is assigned
+ * than {@code null} content (e.g. "{}")
+ * @throws EntityNotFoundException
+ * in case no target with the given {@code targetId} exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/assignedDS", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getAssignedDistributionSet(
+ @PathVariable("targetId") final String targetId);
+
+ /**
+ * Changes the assigned distribution set of a target.
+ *
+ * @param targetId
+ * of the target to change
+ * @param dsId
+ * of the distributionset that is to be assigned
+ * @return http status
+ *
+ * @throws EntityNotFoundException
+ * in case no target with the given {@code targetId} exists.
+ *
+ */
+ @RequestMapping(method = RequestMethod.POST, value = "/{targetId}/assignedDS", consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity postAssignedDistributionSet(@PathVariable("targetId") final String targetId,
+ @RequestBody final DistributionSetAssigmentRest dsId);
+
+ /**
+ * Handles the GET request of retrieving the installed distribution set of
+ * an specific target.
+ *
+ * @param targetId
+ * the ID of the target to retrieve
+ * @return the assigned installed set with status OK, if none is installed
+ * than {@code null} content (e.g. "{}")
+ * @throws EntityNotFoundException
+ * in case no target with the given {@code targetId} exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/installedDS", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getInstalledDistributionSet(
+ @PathVariable("targetId") final String targetId);
+
+}
\ No newline at end of file
diff --git a/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/TargetTagRestApi.java b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/TargetTagRestApi.java
new file mode 100644
index 000000000..59770db08
--- /dev/null
+++ b/hawkbit-rest-api/src/main/java/org/eclipse/hawkbit/rest/resource/api/TargetTagRestApi.java
@@ -0,0 +1,196 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.resource.api;
+
+import java.util.List;
+
+import org.eclipse.hawkbit.rest.resource.RestConstants;
+import org.eclipse.hawkbit.rest.resource.model.tag.AssignedTargetRequestBody;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagPagedList;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TagsRest;
+import org.eclipse.hawkbit.rest.resource.model.tag.TargetTagAssigmentResultRest;
+import org.eclipse.hawkbit.rest.resource.model.target.TargetsRest;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * REST Resource handling for TargetTag CRUD operations.
+ *
+ */
+@RequestMapping(RestConstants.TARGET_TAG_V1_REQUEST_MAPPING)
+public interface TargetTagRestApi {
+
+ /**
+ * Handles the GET request of retrieving all target tags.
+ *
+ * @param pagingOffsetParam
+ * the offset of list of target tags for pagination, might not be
+ * present in the rest request then default value will be applied
+ * @param pagingLimitParam
+ * the limit of the paged request, might not be present in the
+ * rest request then default value will be applied
+ * @param sortParam
+ * the sorting parameter in the request URL, syntax
+ * {@code field:direction, field:direction}
+ * @param rsqlParam
+ * the search parameter in the request URL, syntax
+ * {@code q=name==abc}
+ * @return a list of all target tags for a defined or default page request
+ * with status OK. The response is always paged. In any failure the
+ * JsonResponseExceptionHandler is handling the response.
+ */
+ @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getTargetTags(
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
+ @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam);
+
+ /**
+ * Handles the GET request of retrieving a single target tag.
+ *
+ * @param targetTagId
+ * the ID of the target tag to retrieve
+ *
+ * @return a single target tag with status OK.
+ * @throws EntityNotFoundException
+ * in case the given {@code targetTagId} doesn't exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{targetTagId}", produces = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity getTargetTag(@PathVariable("targetTagId") final Long targetTagId);
+
+ /**
+ * Handles the POST request of creating new target tag. The request body
+ * must always be a list of tags.
+ *
+ * @param tags
+ * the target tags to be created.
+ * @return In case all modules could successful created the ResponseEntity
+ * with status code 201 - Created. The Response Body are the created
+ * target tags but without ResponseBody.
+ */
+ @RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity createTargetTags(@RequestBody final List tags);
+
+ /**
+ *
+ * Handles the PUT request of updating a single targetr tag.
+ *
+ * @param targetTagId
+ * the ID of the target tag
+ * @param restTargetTagRest
+ * the the request body to be updated
+ * @return status OK if update is successful and the updated target tag.
+ * @throws EntityNotFoundException
+ * in case the given {@code targetTagId} doesn't exists.
+ */
+ @RequestMapping(method = RequestMethod.PUT, value = "/{targetTagId}", consumes = { "application/hal+json",
+ MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ public ResponseEntity updateTagretTag(@PathVariable("targetTagId") final Long targetTagId,
+ @RequestBody final TagRequestBodyPut restTargetTagRest);
+
+ /**
+ * Handles the DELETE request for a single target tag.
+ *
+ * @param targetTagId
+ * the ID of the target tag
+ * @return status OK if delete as successfully.
+ * @throws EntityNotFoundException
+ * in case the given {@code targetTagId} doesn't exists.
+ *
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = "/{targetTagId}")
+ public ResponseEntity deleteTargetTag(@PathVariable("targetTagId") final Long targetTagId);
+
+ /**
+ * Handles the GET request of retrieving all assigned targets by the given
+ * tag id.
+ *
+ * @param targetTagId
+ * the ID of the target tag to retrieve
+ *
+ * @return the list of assigned targets.
+ * @throws EntityNotFoundException
+ * in case the given {@code targetTagId} doesn't exists.
+ */
+ @RequestMapping(method = RequestMethod.GET, value = RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
+ public ResponseEntity getAssignedTargets(@PathVariable("targetTagId") final Long targetTagId);
+
+ /**
+ * Handles the POST request to toggle the assignment of targets by the given
+ * tag id.
+ *
+ * @param targetTagId
+ * the ID of the target tag to retrieve
+ * @param assignedTargetRequestBodies
+ * list of target ids to be toggled
+ *
+ * @return the list of assigned targets and unassigned targets.
+ * @throws EntityNotFoundException
+ * in case the given {@code targetTagId} doesn't exists.
+ */
+ @RequestMapping(method = RequestMethod.POST, value = RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING
+ + "/toggleTagAssignment")
+ public ResponseEntity toggleTagAssignment(
+ @PathVariable("targetTagId") final Long targetTagId,
+ @RequestBody final List assignedTargetRequestBodies);
+
+ /**
+ * Handles the POST request to assign targets to the given tag id.
+ *
+ * @param targetTagId
+ * the ID of the target tag to retrieve
+ * @param assignedTargetRequestBodies
+ * list of target ids to be assigned
+ *
+ * @return the list of assigned targets.
+ * @throws EntityNotFoundException
+ * in case the given {@code targetTagId} doesn't exists.
+ */
+ @RequestMapping(method = RequestMethod.POST, value = RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
+ public ResponseEntity assignTargets(@PathVariable("targetTagId") final Long targetTagId,
+ @RequestBody final List assignedTargetRequestBodies);
+
+ /**
+ * Handles the DELETE request to unassign all targets from the given tag id.
+ *
+ * @param targetTagId
+ * the ID of the target tag to retrieve
+ * @return http status code
+ * @throws EntityNotFoundException
+ * in case the given {@code targetTagId} doesn't exists.
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
+ public ResponseEntity unassignTargets(@PathVariable("targetTagId") final Long targetTagId);
+
+ /**
+ * Handles the DELETE request to unassign one target from the given tag id.
+ *
+ * @param targetTagId
+ * the ID of the target tag
+ * @param controllerId
+ * the ID of the target to unassign
+ * @return http status code
+ * @throws EntityNotFoundException
+ * in case the given {@code targetTagId} doesn't exists.
+ */
+ @RequestMapping(method = RequestMethod.DELETE, value = RestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING
+ + "/{controllerId}")
+ public ResponseEntity unassignTarget(@PathVariable("targetTagId") final Long targetTagId,
+ @PathVariable("controllerId") final String controllerId);
+}
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetMapper.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetMapper.java
index 830b47798..9ae133dd5 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetMapper.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetMapper.java
@@ -22,6 +22,8 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
+import org.eclipse.hawkbit.rest.resource.api.DistributionSetRestApi;
+import org.eclipse.hawkbit.rest.resource.api.DistributionSetTypeRestApi;
import org.eclipse.hawkbit.rest.resource.model.MetadataRest;
import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRequestBodyPost;
import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRest;
@@ -169,13 +171,13 @@ public final class DistributionSetMapper {
response.setRequiredMigrationStep(distributionSet.isRequiredMigrationStep());
response.add(
- linkTo(methodOn(DistributionSetResource.class).getDistributionSet(response.getDsId())).withRel("self"));
+ linkTo(methodOn(DistributionSetRestApi.class).getDistributionSet(response.getDsId())).withRel("self"));
response.add(linkTo(
- methodOn(DistributionSetTypeResource.class).getDistributionSetType(distributionSet.getType().getId()))
+ methodOn(DistributionSetTypeRestApi.class).getDistributionSetType(distributionSet.getType().getId()))
.withRel("type"));
- response.add(linkTo(methodOn(DistributionSetResource.class).getMetadata(response.getDsId(),
+ response.add(linkTo(methodOn(DistributionSetRestApi.class).getMetadata(response.getDsId(),
Integer.parseInt(RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET),
Integer.parseInt(RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT), null, null))
.withRel("metadata"));
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetResource.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetResource.java
index b0a245915..a4c71378d 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetResource.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetResource.java
@@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.model.DsMetadataCompositeKey;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
+import org.eclipse.hawkbit.rest.resource.api.DistributionSetRestApi;
import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
import org.eclipse.hawkbit.rest.resource.model.MetadataRest;
import org.eclipse.hawkbit.rest.resource.model.MetadataRestPageList;
@@ -51,25 +52,14 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* REST Resource handling for {@link DistributionSet} CRUD operations.
- *
- *
- *
- *
*/
@RestController
-@RequestMapping(RestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
-public class DistributionSetResource {
+public class DistributionSetResource implements DistributionSetRestApi {
private static final Logger LOG = LoggerFactory.getLogger(DistributionSetResource.class);
@Autowired
@@ -90,32 +80,9 @@ public class DistributionSetResource {
@Autowired
private DistributionSetManagement distributionSetManagement;
- /**
- * Handles the GET request of retrieving all {@link DistributionSet}s within
- * SP.
- *
- * @param pagingOffsetParam
- * the offset of list of sets for pagination, might not be
- * present in the rest request then default value will be applied
- * @param pagingLimitParam
- * the limit of the paged request, might not be present in the
- * rest request then default value will be applied
- * @param sortParam
- * the sorting parameter in the request URL, syntax
- * {@code field:direction, field:direction}
- * @param rsqlParam
- * the search parameter in the request URL, syntax
- * {@code q=name==abc}
- * @return a list of all set for a defined or default page request with
- * status OK. The response is always paged. In any failure the
- * JsonResponseExceptionHandler is handling the response.
- */
- @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
- public ResponseEntity getDistributionSets(
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) {
+ @Override
+ public ResponseEntity getDistributionSets(final int pagingOffsetParam,
+ final int pagingLimitParam, final String sortParam, final String rsqlParam) {
final int sanitizedOffsetParam = PagingUtility.sanitizeOffsetParam(pagingOffsetParam);
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
@@ -124,99 +91,51 @@ public class DistributionSetResource {
final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
final Page findDsPage;
if (rsqlParam != null) {
- findDsPage = distributionSetManagement.findDistributionSetsAll(
+ findDsPage = this.distributionSetManagement.findDistributionSetsAll(
RSQLUtility.parse(rsqlParam, DistributionSetFields.class), pageable, false);
} else {
- findDsPage = distributionSetManagement.findDistributionSetsAll(pageable, false, null);
+ findDsPage = this.distributionSetManagement.findDistributionSetsAll(pageable, false, null);
}
final List rest = DistributionSetMapper.toResponseFromDsList(findDsPage.getContent());
return new ResponseEntity<>(new DistributionSetPagedList(rest, findDsPage.getTotalElements()), HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving a single {@link DistributionSet}
- * within SP.
- *
- * @param distributionSetId
- * the ID of the set to retrieve
- *
- * @return a single {@link DistributionSet} with status OK.
- *
- * @throws EntityNotFoundException
- * in case no {@link DistributionSet} with the given ID exists.
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}", produces = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE })
- public ResponseEntity getDistributionSet(@PathVariable final Long distributionSetId) {
+ @Override
+ public ResponseEntity getDistributionSet(final Long distributionSetId) {
final DistributionSet foundDs = findDistributionSetWithExceptionIfNotFound(distributionSetId);
return new ResponseEntity<>(DistributionSetMapper.toResponse(foundDs), HttpStatus.OK);
}
- /**
- * Handles the POST request of creating new distribution sets within SP. The
- * request body must always be a list of sets. The requests is delegating to
- * the {@link SoftwareManagement#createDistributionSet(DistributionSet))}.
- *
- * @param sets
- * the {@link DistributionSet}s to be created.
- * @return In case all sets could successful created the ResponseEntity with
- * status code 201 - Created but without ResponseBody. In any
- * failure the JsonResponseExceptionHandler is handling the
- * response.
- */
- @RequestMapping(method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE,
- "application/hal+json" }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity createDistributionSets(
- @RequestBody final List sets) {
+ final List sets) {
LOG.debug("creating {} distribution sets", sets.size());
// set default Ds type if ds type is null
- sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(
- systemManagement.getTenantMetadata(currentTenant.getCurrentTenant()).getDefaultDsType().getKey()));
+ sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(this.systemManagement
+ .getTenantMetadata(this.currentTenant.getCurrentTenant()).getDefaultDsType().getKey()));
- final Iterable createdDSets = distributionSetManagement.createDistributionSets(
- DistributionSetMapper.dsFromRequest(sets, softwareManagement, distributionSetManagement));
+ final Iterable createdDSets = this.distributionSetManagement.createDistributionSets(
+ DistributionSetMapper.dsFromRequest(sets, this.softwareManagement, this.distributionSetManagement));
LOG.debug("{} distribution sets created, return status {}", sets.size(), HttpStatus.CREATED);
return new ResponseEntity<>(DistributionSetMapper.toResponseDistributionSets(createdDSets), HttpStatus.CREATED);
}
- /**
- * Handles the DELETE request for a single {@link DistributionSet} within
- * SP.
- *
- * @param distributionSetId
- * the ID of the {@link DistributionSet} to delete
- * @return status OK if delete as successful.
- *
- */
- @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetId}")
- public ResponseEntity deleteDistributionSet(@PathVariable final Long distributionSetId) {
+ @Override
+ public ResponseEntity deleteDistributionSet(final Long distributionSetId) {
final DistributionSet set = findDistributionSetWithExceptionIfNotFound(distributionSetId);
- distributionSetManagement.deleteDistributionSet(set);
+ this.distributionSetManagement.deleteDistributionSet(set);
return new ResponseEntity<>(HttpStatus.OK);
}
- /**
- * Handles the UPDATE request for a single {@link DistributionSet} within
- * SP.
- *
- * @param distributionSetId
- * the ID of the {@link DistributionSet} to delete
- * @param toUpdate
- * with the data that needs updating
- *
- * @return status OK if update as successful with updated content.
- *
- */
- @RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetId}", consumes = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
- public ResponseEntity updateDistributionSet(@PathVariable final Long distributionSetId,
- @RequestBody final DistributionSetRequestBodyPut toUpdate) {
+ @Override
+ public ResponseEntity updateDistributionSet(final Long distributionSetId,
+ final DistributionSetRequestBodyPut toUpdate) {
final DistributionSet set = findDistributionSetWithExceptionIfNotFound(distributionSetId);
if (toUpdate.getDescription() != null) {
@@ -231,38 +150,13 @@ public class DistributionSetResource {
set.setVersion(toUpdate.getVersion());
}
return new ResponseEntity<>(
- DistributionSetMapper.toResponse(distributionSetManagement.updateDistributionSet(set)), HttpStatus.OK);
+ DistributionSetMapper.toResponse(this.distributionSetManagement.updateDistributionSet(set)),
+ HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving assigned targets to a specific
- * distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set to retrieve the assigned
- * targets
- * @param pagingOffsetParam
- * the offset of list of targets for pagination, might not be
- * present in the rest request then default value will be applied
- * @param pagingLimitParam
- * the limit of the paged request, might not be present in the
- * rest request then default value will be applied
- * @param sortParam
- * the sorting parameter in the request URL, syntax
- * {@code field:direction, field:direction}
- * @param rsqlParam
- * the search parameter in the request URL, syntax
- * {@code q=name==abc}
- * @return status OK if get request is successful with the paged list of
- * targets
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/assignedTargets", produces = {
- MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
- public ResponseEntity getAssignedTargets(@PathVariable final Long distributionSetId,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) {
+ @Override
+ public ResponseEntity getAssignedTargets(final Long distributionSetId, final int pagingOffsetParam,
+ final int pagingLimitParam, final String sortParam, final String rsqlParam) {
// check if distribution set exists otherwise throw exception
// immediately
@@ -275,45 +169,19 @@ public class DistributionSetResource {
final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
final Page targetsAssignedDS;
if (rsqlParam != null) {
- targetsAssignedDS = targetManagement.findTargetByAssignedDistributionSet(distributionSetId,
+ targetsAssignedDS = this.targetManagement.findTargetByAssignedDistributionSet(distributionSetId,
RSQLUtility.parse(rsqlParam, TargetFields.class), pageable);
} else {
- targetsAssignedDS = targetManagement.findTargetByAssignedDistributionSet(distributionSetId, pageable);
+ targetsAssignedDS = this.targetManagement.findTargetByAssignedDistributionSet(distributionSetId, pageable);
}
return new ResponseEntity<>(new TargetPagedList(TargetMapper.toResponse(targetsAssignedDS.getContent()),
targetsAssignedDS.getTotalElements()), HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving installed targets to a specific
- * distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set to retrieve the assigned
- * targets
- * @param pagingOffsetParam
- * the offset of list of targets for pagination, might not be
- * present in the rest request then default value will be applied
- * @param pagingLimitParam
- * the limit of the paged request, might not be present in the
- * rest request then default value will be applied
- * @param sortParam
- * the sorting parameter in the request URL, syntax
- * {@code field:direction, field:direction}
- * @param rsqlParam
- * the search parameter in the request URL, syntax
- * {@code q=name==abc}
- * @return status OK if get request is successful with the paged list of
- * targets
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/installedTargets", produces = {
- MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
- public ResponseEntity getInstalledTargets(@PathVariable final Long distributionSetId,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) {
+ @Override
+ public ResponseEntity getInstalledTargets(final Long distributionSetId,
+ final int pagingOffsetParam, final int pagingLimitParam, final String sortParam, final String rsqlParam) {
// check if distribution set exists otherwise throw exception
// immediately
findDistributionSetWithExceptionIfNotFound(distributionSetId);
@@ -325,36 +193,22 @@ public class DistributionSetResource {
final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
final Page targetsInstalledDS;
if (rsqlParam != null) {
- targetsInstalledDS = targetManagement.findTargetByInstalledDistributionSet(distributionSetId,
+ targetsInstalledDS = this.targetManagement.findTargetByInstalledDistributionSet(distributionSetId,
RSQLUtility.parse(rsqlParam, TargetFields.class), pageable);
} else {
- targetsInstalledDS = targetManagement.findTargetByInstalledDistributionSet(distributionSetId, pageable);
+ targetsInstalledDS = this.targetManagement.findTargetByInstalledDistributionSet(distributionSetId,
+ pageable);
}
return new ResponseEntity<>(new TargetPagedList(TargetMapper.toResponse(targetsInstalledDS.getContent()),
targetsInstalledDS.getTotalElements()), HttpStatus.OK);
}
- /**
- * Handles the POST request of assigning multiple targets to a single
- * distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set within the URL path parameter
- * @param targetIds
- * the IDs of the target which should get assigned to the
- * distribution set given in the response body
- * @return status OK if the assignment of the targets was successful and a
- * complex return body which contains information about the assigned
- * targets and the already assigned targets counters
- */
- @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetId}/assignedTargets", consumes = {
- "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
- public ResponseEntity createAssignedTarget(@PathVariable final Long distributionSetId,
- @RequestBody final List targetIds) {
+ @Override
+ public ResponseEntity createAssignedTarget(final Long distributionSetId,
+ final List targetIds) {
- final DistributionSetAssignmentResult assignDistributionSet = deployManagament.assignDistributionSet(
+ final DistributionSetAssignmentResult assignDistributionSet = this.deployManagament.assignDistributionSet(
distributionSetId,
targetIds.stream()
.map(t -> new TargetWithActionType(t.getId(),
@@ -364,33 +218,9 @@ public class DistributionSetResource {
return new ResponseEntity<>(DistributionSetMapper.toResponse(assignDistributionSet), HttpStatus.OK);
}
- /**
- * Gets a paged list of meta data for a distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set for the meta data
- * @param pagingOffsetParam
- * the offset of list of targets for pagination, might not be
- * present in the rest request then default value will be applied
- * @param pagingLimitParam
- * the limit of the paged request, might not be present in the
- * rest request then default value will be applied
- * @param sortParam
- * the sorting parameter in the request URL, syntax
- * {@code field:direction, field:direction}
- * @param rsqlParam
- * the search parameter in the request URL, syntax
- * {@code q=key==abc}
- * @return status OK if get request is successful with the paged list of
- * meta data
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/metadata", produces = {
- MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
- public ResponseEntity getMetadata(@PathVariable final Long distributionSetId,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) {
+ @Override
+ public ResponseEntity getMetadata(final Long distributionSetId, final int pagingOffsetParam,
+ final int pagingLimitParam, final String sortParam, final String rsqlParam) {
// check if distribution set exists otherwise throw exception
// immediately
@@ -404,11 +234,11 @@ public class DistributionSetResource {
final Page metaDataPage;
if (rsqlParam != null) {
- metaDataPage = distributionSetManagement.findDistributionSetMetadataByDistributionSetId(distributionSetId,
- RSQLUtility.parse(rsqlParam, DistributionSetMetadataFields.class), pageable);
+ metaDataPage = this.distributionSetManagement.findDistributionSetMetadataByDistributionSetId(
+ distributionSetId, RSQLUtility.parse(rsqlParam, DistributionSetMetadataFields.class), pageable);
} else {
- metaDataPage = distributionSetManagement.findDistributionSetMetadataByDistributionSetId(distributionSetId,
- pageable);
+ metaDataPage = this.distributionSetManagement
+ .findDistributionSetMetadataByDistributionSetId(distributionSetId, pageable);
}
return new ResponseEntity<>(
@@ -418,119 +248,59 @@ public class DistributionSetResource {
}
- /**
- * Gets a single meta data value for a specific key of a distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set to get the meta data from
- * @param metadataKey
- * the key of the meta data entry to retrieve the value from
- * @return status OK if get request is successful with the value of the meta
- * data
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/metadata/{metadataKey}", produces = {
- MediaType.APPLICATION_JSON_VALUE })
- public ResponseEntity getMetadataValue(@PathVariable final Long distributionSetId,
- @PathVariable final String metadataKey) {
+ @Override
+ public ResponseEntity getMetadataValue(final Long distributionSetId, final String metadataKey) {
// check if distribution set exists otherwise throw exception
// immediately
final DistributionSet ds = findDistributionSetWithExceptionIfNotFound(distributionSetId);
- final DistributionSetMetadata findOne = distributionSetManagement
+ final DistributionSetMetadata findOne = this.distributionSetManagement
.findOne(new DsMetadataCompositeKey(ds, metadataKey));
return ResponseEntity. ok(DistributionSetMapper.toResponseDsMetadata(findOne));
}
- /**
- * Updates a single meta data value of a distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set to update the meta data entry
- * @param metadataKey
- * the key of the meta data to update the value
- * @return status OK if the update request is successful and the updated
- * meta data result
- */
- @RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetId}/metadata/{metadataKey}", produces = {
- MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
- public ResponseEntity updateMetadata(@PathVariable final Long distributionSetId,
- @PathVariable final String metadataKey, @RequestBody final MetadataRest metadata) {
+ @Override
+ public ResponseEntity updateMetadata(final Long distributionSetId, final String metadataKey,
+ final MetadataRest metadata) {
// check if distribution set exists otherwise throw exception
// immediately
final DistributionSet ds = findDistributionSetWithExceptionIfNotFound(distributionSetId);
- final DistributionSetMetadata updated = distributionSetManagement
+ final DistributionSetMetadata updated = this.distributionSetManagement
.updateDistributionSetMetadata(new DistributionSetMetadata(metadataKey, ds, metadata.getValue()));
return ResponseEntity.ok(DistributionSetMapper.toResponseDsMetadata(updated));
}
- /**
- * Deletes a single meta data entry from the distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set to delete the meta data entry
- * @param metadataKey
- * the key of the meta data to delete
- * @return status OK if the delete request is successful
- */
- @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetId}/metadata/{metadataKey}")
- public ResponseEntity deleteMetadata(@PathVariable final Long distributionSetId,
- @PathVariable final String metadataKey) {
+ @Override
+ public ResponseEntity deleteMetadata(final Long distributionSetId, final String metadataKey) {
// check if distribution set exists otherwise throw exception
// immediately
final DistributionSet ds = findDistributionSetWithExceptionIfNotFound(distributionSetId);
- distributionSetManagement.deleteDistributionSetMetadata(new DsMetadataCompositeKey(ds, metadataKey));
+ this.distributionSetManagement.deleteDistributionSetMetadata(new DsMetadataCompositeKey(ds, metadataKey));
return ResponseEntity.ok().build();
}
- /**
- * Creates a list of meta data for a specific distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set to create meta data for
- * @param metadataRest
- * the list of meta data entries to create
- * @return status created if post request is successful with the value of
- * the created meta data
- */
- @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetId}/metadata", consumes = {
- MediaType.APPLICATION_JSON_VALUE,
- "application/hal+json" }, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
- public ResponseEntity> createMetadata(@PathVariable final Long distributionSetId,
- @RequestBody final List metadataRest) {
+ @Override
+ public ResponseEntity> createMetadata(final Long distributionSetId,
+ final List metadataRest) {
// check if distribution set exists otherwise throw exception
// immediately
final DistributionSet ds = findDistributionSetWithExceptionIfNotFound(distributionSetId);
- final List created = distributionSetManagement
+ final List created = this.distributionSetManagement
.createDistributionSetMetadata(DistributionSetMapper.fromRequestDsMetadata(ds, metadataRest));
return new ResponseEntity<>(DistributionSetMapper.toResponseDsMetadata(created), HttpStatus.CREATED);
}
- /**
- * Assigns a list of software modules to a distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set to assign software modules for
- * @param softwareModuleIDs
- * the list of software modules ids to assign
- * @return {@link HttpStatus#OK}
- *
- * @throws EntityNotFoundException
- * in case no distribution set with the given
- * {@code distributionSetId} exists.
- */
- @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetId}/assignedSM", consumes = {
- MediaType.APPLICATION_JSON_VALUE,
- "application/hal+json" }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
- public ResponseEntity assignSoftwareModules(@PathVariable final Long distributionSetId,
- @RequestBody final List softwareModuleIDs) {
+ @Override
+ public ResponseEntity assignSoftwareModules(final Long distributionSetId,
+ final List softwareModuleIDs) {
// check if distribution set exists otherwise throw exception
// immediately
final DistributionSet ds = findDistributionSetWithExceptionIfNotFound(distributionSetId);
final Set softwareModuleToBeAssigned = new HashSet<>();
for (final SoftwareModuleAssigmentRest sm : softwareModuleIDs) {
- final SoftwareModule softwareModule = softwareManagement.findSoftwareModuleById(sm.getId());
+ final SoftwareModule softwareModule = this.softwareManagement.findSoftwareModuleById(sm.getId());
if (softwareModule != null) {
softwareModuleToBeAssigned.add(softwareModule);
} else {
@@ -538,63 +308,23 @@ public class DistributionSetResource {
}
}
// Add Softwaremodules to DisSet only if all of them were found
- distributionSetManagement.assignSoftwareModules(ds, softwareModuleToBeAssigned);
+ this.distributionSetManagement.assignSoftwareModules(ds, softwareModuleToBeAssigned);
return new ResponseEntity<>(HttpStatus.OK);
}
- /**
- * Deletes the assignment of the software module form the distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution set to reject the software module
- * for
- * @param softwareModuleId
- * the software module id to get rejected form the distribution
- * set
- * @return status OK if rejection was successful.
- * @throws EntityNotFoundException
- * in case no distribution set with the given
- * {@code distributionSetId} exists.
- */
- @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetId}/assignedSM/{softwareModuleId}")
- public ResponseEntity deleteAssignSoftwareModules(@PathVariable final Long distributionSetId,
- @PathVariable final Long softwareModuleId) {
+ @Override
+ public ResponseEntity deleteAssignSoftwareModules(final Long distributionSetId, final Long softwareModuleId) {
// check if distribution set and software module exist otherwise throw
// exception immediately
final DistributionSet ds = findDistributionSetWithExceptionIfNotFound(distributionSetId);
final SoftwareModule sm = findSoftwareModuleWithExceptionIfNotFound(softwareModuleId);
- distributionSetManagement.unassignSoftwareModule(ds, sm);
+ this.distributionSetManagement.unassignSoftwareModule(ds, sm);
return ResponseEntity.ok().build();
}
- /**
- * Handles the GET request for retrieving the assigned software modules of a
- * specific distribution set.
- *
- * @param distributionSetId
- * the ID of the distribution to retrieve
- * @param pagingOffsetParam
- * the offset of list of sets for pagination, might not be
- * present in the rest request then default value will be applied
- * @param pagingLimitParam
- * the limit of the paged request, might not be present in the
- * rest request then default value will be applied
- * @param sortParam
- * the sorting parameter in the request URL, syntax
- * {@code field:direction, field:direction}
- * @return a list of the assigned software modules of a distribution set
- * with status OK, if none is assigned than {@code null}
- * @throws EntityNotFoundException
- * in case no distribution set with the given
- * {@code distributionSetId} exists.
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/assignedSM", produces = {
- "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
- public ResponseEntity getAssignedSoftwareModules(
- @PathVariable final Long distributionSetId,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam) {
+ @Override
+ public ResponseEntity getAssignedSoftwareModules(final Long distributionSetId,
+ final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
// check if distribution set exists otherwise throw exception
// immediately
final DistributionSet foundDs = findDistributionSetWithExceptionIfNotFound(distributionSetId);
@@ -602,7 +332,7 @@ public class DistributionSetResource {
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
final Sort sorting = PagingUtility.sanitizeSoftwareModuleSortParam(sortParam);
final Pageable pageable = new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting);
- final Page softwaremodules = softwareManagement.findSoftwareModuleByAssignedTo(pageable,
+ final Page softwaremodules = this.softwareManagement.findSoftwareModuleByAssignedTo(pageable,
foundDs);
return new ResponseEntity<>(
new SoftwareModulePagedList(SoftwareModuleMapper.toResponse(softwaremodules.getContent()),
@@ -611,7 +341,7 @@ public class DistributionSetResource {
}
private DistributionSet findDistributionSetWithExceptionIfNotFound(final Long distributionSetId) {
- final DistributionSet set = distributionSetManagement.findDistributionSetById(distributionSetId);
+ final DistributionSet set = this.distributionSetManagement.findDistributionSetById(distributionSetId);
if (set == null) {
throw new EntityNotFoundException("DistributionSet with Id {" + distributionSetId + "} does not exist");
}
@@ -620,7 +350,7 @@ public class DistributionSetResource {
}
private SoftwareModule findSoftwareModuleWithExceptionIfNotFound(final Long softwareModuleId) {
- final SoftwareModule sm = softwareManagement.findSoftwareModuleById(softwareModuleId);
+ final SoftwareModule sm = this.softwareManagement.findSoftwareModuleById(softwareModuleId);
if (sm == null) {
throw new EntityNotFoundException("SoftwareModule with Id {" + softwareModuleId + "} does not exist");
}
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTagResource.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTagResource.java
index 99e22436e..c395863ab 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTagResource.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTagResource.java
@@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssigmentResult;
import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
+import org.eclipse.hawkbit.rest.resource.api.DistributionSetTagRestApi;
import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetsRest;
import org.eclipse.hawkbit.rest.resource.model.tag.AssignedDistributionSetRequestBody;
import org.eclipse.hawkbit.rest.resource.model.tag.DistributionSetTagAssigmentResultRest;
@@ -34,13 +35,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
@@ -48,8 +43,7 @@ import org.springframework.web.bind.annotation.RestController;
*
*/
@RestController
-@RequestMapping(RestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING)
-public class DistributionSetTagResource {
+public class DistributionSetTagResource implements DistributionSetTagRestApi {
private static final Logger LOG = LoggerFactory.getLogger(DistributionSetTagResource.class);
@Autowired
@@ -58,32 +52,9 @@ public class DistributionSetTagResource {
@Autowired
private DistributionSetManagement distributionSetManagement;
- /**
- * Handles the GET request of retrieving all DistributionSet tags.
- *
- * @param pagingOffsetParam
- * the offset of list of DistributionSet tags for pagination,
- * might not be present in the rest request then default value
- * will be applied
- * @param pagingLimitParam
- * the limit of the paged request, might not be present in the
- * rest request then default value will be applied
- * @param sortParam
- * the sorting parameter in the request URL, syntax
- * {@code field:direction, field:direction}
- * @param rsqlParam
- * the search parameter in the request URL, syntax
- * {@code q=name==abc}
- * @return a list of all target tags for a defined or default page request
- * with status OK. The response is always paged. In any failure the
- * JsonResponseExceptionHandler is handling the response.
- */
- @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
- public ResponseEntity getDistributionSetTags(
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) {
+ @Override
+ public ResponseEntity getDistributionSetTags(final int pagingOffsetParam, final int pagingLimitParam,
+ final String sortParam, final String rsqlParam) {
final int sanitizedOffsetParam = PagingUtility.sanitizeOffsetParam(pagingOffsetParam);
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
@@ -93,11 +64,11 @@ public class DistributionSetTagResource {
final Slice findTargetsAll;
final Long countTargetsAll;
if (rsqlParam == null) {
- findTargetsAll = tagManagement.findAllDistributionSetTags(pageable);
- countTargetsAll = tagManagement.countTargetTags();
+ findTargetsAll = this.tagManagement.findAllDistributionSetTags(pageable);
+ countTargetsAll = this.tagManagement.countTargetTags();
} else {
- final Page findTargetPage = tagManagement
+ final Page findTargetPage = this.tagManagement
.findAllDistributionSetTags(RSQLUtility.parse(rsqlParam, TagFields.class), pageable);
countTargetsAll = findTargetPage.getTotalElements();
findTargetsAll = findTargetPage;
@@ -108,141 +79,63 @@ public class DistributionSetTagResource {
return new ResponseEntity<>(new TagPagedList(rest, countTargetsAll), HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving a single distribution set tag.
- *
- * @param distributionsetTagId
- * the ID of the distribution set tag to retrieve
- *
- * @return a single distribution set tag with status OK.
- * @throws EntityNotFoundException
- * in case the given {@code distributionsetTagId} doesn't
- * exists.
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionsetTagId}", produces = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE })
- public ResponseEntity getDistributionSetTag(@PathVariable final Long distributionsetTagId) {
+ @Override
+ public ResponseEntity getDistributionSetTag(final Long distributionsetTagId) {
final DistributionSetTag tag = findDistributionTagById(distributionsetTagId);
return new ResponseEntity<>(TagMapper.toResponse(tag), HttpStatus.OK);
}
- /**
- * Handles the POST request of creating new distribution set tag. The
- * request body must always be a list of tags.
- *
- * @param tags
- * the distribution set tags to be created.
- * @return In case all modules could successful created the ResponseEntity
- * with status code 201 - Created. The Response Body are the created
- * distribution set tags but without ResponseBody.
- */
- @RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
- public ResponseEntity createDistributionSetTags(@RequestBody final List tags) {
+ @Override
+ public ResponseEntity createDistributionSetTags(final List tags) {
LOG.debug("creating {} ds tags", tags.size());
- final List createdTags = tagManagement
+ final List createdTags = this.tagManagement
.createDistributionSetTags(TagMapper.mapDistributionSetTagFromRequest(tags));
return new ResponseEntity<>(TagMapper.toResponseDistributionSetTag(createdTags), HttpStatus.CREATED);
}
- /**
- *
- * Handles the PUT request of updating a single distribution set tag.
- *
- * @param distributionsetTagId
- * the ID of the distribution set tag
- * @param restDSTagRest
- * the the request body to be updated
- * @return status OK if update is successful and the updated distribution
- * set tag.
- * @throws EntityNotFoundException
- * in case the given {@code distributionsetTagId} doesn't
- * exists.
- */
- @RequestMapping(method = RequestMethod.PUT, value = "/{distributionsetTagId}", consumes = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
- public ResponseEntity updateDistributionSetTag(@PathVariable final Long distributionsetTagId,
- @RequestBody final TagRequestBodyPut restDSTagRest) {
+ @Override
+ public ResponseEntity updateDistributionSetTag(final Long distributionsetTagId,
+ final TagRequestBodyPut restDSTagRest) {
LOG.debug("update {} ds tag", restDSTagRest);
final DistributionSetTag distributionSetTag = findDistributionTagById(distributionsetTagId);
TagMapper.updateTag(restDSTagRest, distributionSetTag);
- final DistributionSetTag updateDistributionSetTag = tagManagement.updateDistributionSetTag(distributionSetTag);
+ final DistributionSetTag updateDistributionSetTag = this.tagManagement
+ .updateDistributionSetTag(distributionSetTag);
LOG.debug("ds tag updated");
return new ResponseEntity<>(TagMapper.toResponse(updateDistributionSetTag), HttpStatus.OK);
}
- /**
- * Handles the DELETE request for a single distribution set tag.
- *
- * @param distributionsetTagId
- * the ID of the distribution set tag
- * @return status OK if delete as successfully.
- * @throws EntityNotFoundException
- * in case the given {@code distributionsetTagId} doesn't
- * exists.
- *
- */
- @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionsetTagId}")
- public ResponseEntity deleteDistributionSetTag(@PathVariable final Long distributionsetTagId) {
+ @Override
+ public ResponseEntity deleteDistributionSetTag(final Long distributionsetTagId) {
LOG.debug("Delete {} distribution set tag", distributionsetTagId);
final DistributionSetTag tag = findDistributionTagById(distributionsetTagId);
- tagManagement.deleteDistributionSetTag(tag.getName());
+ this.tagManagement.deleteDistributionSetTag(tag.getName());
return new ResponseEntity<>(HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving all assigned distribution sets by
- * the given tag id.
- *
- * @param distributionsetTagId
- * the ID of the distribution set tag
- *
- * @return the list of assigned distribution sets.
- * @throws EntityNotFoundException
- * in case the given {@code distributionsetTagId} doesn't
- * exists.
- */
- @RequestMapping(method = RequestMethod.GET, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
- public ResponseEntity getAssignedDistributionSets(
- @PathVariable final Long distributionsetTagId) {
+ @Override
+ public ResponseEntity getAssignedDistributionSets(final Long distributionsetTagId) {
final DistributionSetTag tag = findDistributionTagById(distributionsetTagId);
return new ResponseEntity<>(
DistributionSetMapper.toResponseDistributionSets(tag.getAssignedToDistributionSet()), HttpStatus.OK);
}
- /**
- * Handles the POST request to toggle the assignment of distribution sets by
- * the given tag id.
- *
- * @param distributionsetTagIds
- * the ID of the distribution set tag to retrieve
- * @param assignedDSRequestBodies
- * list of distribution set ids to be toggled
- *
- * @return the list of assigned distribution sets and unassigned
- * distribution sets.
- * @throws EntityNotFoundException
- * in case the given {@code distributionsetTagId} doesn't
- * exists.
- */
- @RequestMapping(method = RequestMethod.POST, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING
- + "/toggleTagAssignment")
- public ResponseEntity toggleTagAssignment(
- @PathVariable final Long distributionsetTagId,
- @RequestBody final List assignedDSRequestBodies) {
+ @Override
+ public ResponseEntity toggleTagAssignment(final Long distributionsetTagId,
+ final List assignedDSRequestBodies) {
LOG.debug("Toggle distribution set assignment {} for ds tag {}", assignedDSRequestBodies.size(),
distributionsetTagId);
final DistributionSetTag tag = findDistributionTagById(distributionsetTagId);
- final DistributionSetTagAssigmentResult assigmentResult = distributionSetManagement
+ final DistributionSetTagAssigmentResult assigmentResult = this.distributionSetManagement
.toggleTagAssignment(findDistributionSetIds(assignedDSRequestBodies), tag.getName());
final DistributionSetTagAssigmentResultRest tagAssigmentResultRest = new DistributionSetTagAssigmentResultRest();
@@ -257,44 +150,20 @@ public class DistributionSetTagResource {
return new ResponseEntity<>(tagAssigmentResultRest, HttpStatus.OK);
}
- /**
- * Handles the POST request to assign distribution sets to the given tag id.
- *
- * @param distributionsetTagId
- * the ID of the distribution set tag to retrieve
- * @param assignedDSRequestBodies
- * list of distribution sets ids to be assigned
- *
- * @return the list of assigned distribution set.
- * @throws EntityNotFoundException
- * in case the given {@code distributionsetTagId} doesn't
- * exists.
- */
- @RequestMapping(method = RequestMethod.POST, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
- public ResponseEntity assignDistributionSets(@PathVariable final Long distributionsetTagId,
- @RequestBody final List assignedDSRequestBodies) {
+ @Override
+ public ResponseEntity assignDistributionSets(final Long distributionsetTagId,
+ final List assignedDSRequestBodies) {
LOG.debug("Assign DistributionSet {} for ds tag {}", assignedDSRequestBodies.size(), distributionsetTagId);
final DistributionSetTag tag = findDistributionTagById(distributionsetTagId);
- final List assignedDs = distributionSetManagement
+ final List assignedDs = this.distributionSetManagement
.assignTag(findDistributionSetIds(assignedDSRequestBodies), tag);
LOG.debug("Assignd DistributionSet {}", assignedDs.size());
return new ResponseEntity<>(DistributionSetMapper.toResponseDistributionSets(assignedDs), HttpStatus.OK);
}
- /**
- * Handles the DELETE request to unassign all distribution set from the
- * given tag id.
- *
- * @param distributionsetTagId
- * the ID of the distribution set tag to retrieve
- * @return http status code
- * @throws EntityNotFoundException
- * in case the given {@code distributionsetTagId} doesn't
- * exists.
- */
- @RequestMapping(method = RequestMethod.DELETE, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING)
- public ResponseEntity unassignDistributionSets(@PathVariable final Long distributionsetTagId) {
+ @Override
+ public ResponseEntity unassignDistributionSets(final Long distributionsetTagId) {
LOG.debug("Unassign all DS for ds tag {}", distributionsetTagId);
final DistributionSetTag tag = findDistributionTagById(distributionsetTagId);
if (tag.getAssignedToDistributionSet() == null) {
@@ -302,36 +171,22 @@ public class DistributionSetTagResource {
return new ResponseEntity<>(HttpStatus.OK);
}
- final List distributionSets = distributionSetManagement.unAssignAllDistributionSetsByTag(tag);
+ final List distributionSets = this.distributionSetManagement
+ .unAssignAllDistributionSetsByTag(tag);
LOG.debug("Unassigned ds {}", distributionSets.size());
return new ResponseEntity<>(HttpStatus.OK);
}
- /**
- * Handles the DELETE request to unassign one distribution set from the
- * given tag id.
- *
- * @param distributionsetTagId
- * the ID of the distribution set tag
- * @param distributionsetId
- * the ID of the distribution set to unassign
- * @return http status code
- * @throws EntityNotFoundException
- * in case the given {@code distributionsetTagId} doesn't
- * exists.
- */
- @RequestMapping(method = RequestMethod.DELETE, value = RestConstants.DISTRIBUTIONSET_REQUEST_MAPPING
- + "/{distributionsetId}")
- public ResponseEntity unassignDistributionSet(@PathVariable final Long distributionsetTagId,
- @PathVariable final Long distributionsetId) {
+ @Override
+ public ResponseEntity unassignDistributionSet(final Long distributionsetTagId, final Long distributionsetId) {
LOG.debug("Unassign ds {} for ds tag {}", distributionsetId, distributionsetTagId);
final DistributionSetTag tag = findDistributionTagById(distributionsetTagId);
- distributionSetManagement.unAssignTag(distributionsetId, tag);
+ this.distributionSetManagement.unAssignTag(distributionsetId, tag);
return new ResponseEntity<>(HttpStatus.OK);
}
private DistributionSetTag findDistributionTagById(final Long distributionsetTagId) {
- final DistributionSetTag tag = tagManagement.findDistributionSetTagById(distributionsetTagId);
+ final DistributionSetTag tag = this.tagManagement.findDistributionSetTagById(distributionsetTagId);
if (tag == null) {
throw new EntityNotFoundException("Distribution Tag with Id {" + distributionsetTagId + "} does not exist");
}
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTypeMapper.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTypeMapper.java
index 0550e0fc5..92923cb56 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTypeMapper.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTypeMapper.java
@@ -18,6 +18,7 @@ import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
+import org.eclipse.hawkbit.rest.resource.api.DistributionSetTypeRestApi;
import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRequestBodyPost;
import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRest;
import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypesRest;
@@ -101,13 +102,13 @@ final class DistributionSetTypeMapper {
result.setKey(type.getKey());
result.setModuleId(type.getId());
- result.add(linkTo(methodOn(DistributionSetTypeResource.class).getDistributionSetType(result.getModuleId()))
+ result.add(linkTo(methodOn(DistributionSetTypeRestApi.class).getDistributionSetType(result.getModuleId()))
.withRel("self"));
- result.add(linkTo(methodOn(DistributionSetTypeResource.class).getMandatoryModules(result.getModuleId()))
+ result.add(linkTo(methodOn(DistributionSetTypeRestApi.class).getMandatoryModules(result.getModuleId()))
.withRel(RestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULES));
- result.add(linkTo(methodOn(DistributionSetTypeResource.class).getOptionalModules(result.getModuleId()))
+ result.add(linkTo(methodOn(DistributionSetTypeRestApi.class).getOptionalModules(result.getModuleId()))
.withRel(RestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULES));
return result;
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTypeResource.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTypeResource.java
index 19cf94f04..700ef3d96 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTypeResource.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DistributionSetTypeResource.java
@@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
+import org.eclipse.hawkbit.rest.resource.api.DistributionSetTypeRestApi;
import org.eclipse.hawkbit.rest.resource.model.IdRest;
import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypePagedList;
import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRequestBodyPost;
@@ -33,12 +34,9 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@@ -47,12 +45,9 @@ import org.springframework.web.bind.annotation.RestController;
* {@link Artifact} CRUD operations.
*
*
- *
- *
*/
@RestController
-@RequestMapping(RestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING)
-public class DistributionSetTypeResource {
+public class DistributionSetTypeResource implements DistributionSetTypeRestApi {
@Autowired
private SoftwareManagement softwareManagement;
@@ -60,30 +55,7 @@ public class DistributionSetTypeResource {
@Autowired
private DistributionSetManagement distributionSetManagement;
- /**
- * Handles the GET request of retrieving all {@link DistributionSetType}s
- * within SP.
- *
- * @param pagingOffsetParam
- * the offset of list of modules for pagination, might not be
- * present in the rest request then default value will be applied
- * @param pagingLimitParam
- * the limit of the paged request, might not be present in the
- * rest request then default value will be applied
- * @param sortParam
- * the sorting parameter in the request URL, syntax
- * {@code field:direction, field:direction}
- * @param rsqlParam
- * the search parameter in the request URL, syntax
- * {@code q=name==abc}
- *
- * @return a list of all {@link DistributionSetType} for a defined or
- * default page request with status OK. The response is always
- * paged. In any failure the JsonResponseExceptionHandler is
- * handling the response.
- */
- @RequestMapping(method = RequestMethod.GET, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
-
+ @Override
public ResponseEntity getDistributionSetTypes(
@RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
@RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
@@ -112,19 +84,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(new DistributionSetTypePagedList(rest, countModulesAll), HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving a single
- * {@link DistributionSetType} within SP.
- *
- * @param distributionSetTypeId
- * the ID of the module type to retrieve
- *
- * @return a single softwareModule with status OK.
- * @throws EntityNotFoundException
- * in case no with the given {@code softwareModuleId} exists.
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}", produces = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity getDistributionSetType(
@PathVariable final Long distributionSetTypeId) {
final DistributionSetType foundType = findDistributionSetTypeWithExceptionIfNotFound(distributionSetTypeId);
@@ -132,15 +92,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(DistributionSetTypeMapper.toResponse(foundType), HttpStatus.OK);
}
- /**
- * Handles the DELETE request for a single Distribution Set Type within SP.
- *
- * @param distributionSetTypeId
- * the ID of the module to retrieve
- * @return status OK if delete as sucessfull.
- *
- */
- @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetTypeId}")
+ @Override
public ResponseEntity deleteDistributionSetType(@PathVariable final Long distributionSetTypeId) {
final DistributionSetType module = findDistributionSetTypeWithExceptionIfNotFound(distributionSetTypeId);
@@ -149,17 +101,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(HttpStatus.OK);
}
- /**
- * Handles the PUT request of updating a Distribution Set Type within SP.
- *
- * @param distributionSetTypeId
- * the ID of the software module in the URL
- * @param restDistributionSetType
- * the module type to be updated.
- * @return status OK if update is successful
- */
- @RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetTypeId}", consumes = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity updateDistributionSetType(
@PathVariable final Long distributionSetTypeId,
@RequestBody final DistributionSetTypeRequestBodyPut restDistributionSetType) {
@@ -176,19 +118,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(DistributionSetTypeMapper.toResponse(updatedDistributionSetType), HttpStatus.OK);
}
- /**
- * Handles the POST request of creating new {@link DistributionSetType}s
- * within SP. The request body must always be a list of types.
- *
- * @param distributionSetTypes
- * the modules to be created.
- * @return In case all modules could successful created the ResponseEntity
- * with status code 201 - Created but without ResponseBody. In any
- * failure the JsonResponseExceptionHandler is handling the
- * response.
- */
- @RequestMapping(method = RequestMethod.POST, consumes = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity createDistributionSetTypes(
@RequestBody final List distributionSetTypes) {
@@ -208,17 +138,7 @@ public class DistributionSetTypeResource {
return module;
}
- /**
- * Handles the GET request of retrieving the list of mandatory software
- * module types in that distribution set type.
- *
- * @param distributionSetTypeId
- * of the {@link DistributionSetType}.
- * @return Unpaged list of module types and OK in case of success.
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
- + RestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES, produces = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity getMandatoryModules(@PathVariable final Long distributionSetTypeId) {
final DistributionSetType foundType = findDistributionSetTypeWithExceptionIfNotFound(distributionSetTypeId);
@@ -229,19 +149,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(rest, HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving the single mandatory software
- * module type in that distribution set type.
- *
- * @param distributionSetTypeId
- * of the {@link DistributionSetType}.
- * @param softwareModuleTypeId
- * of {@link SoftwareModuleType}.
- * @return Unpaged list of module types and OK in case of success.
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
- + RestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES
- + "/{softwareModuleTypeId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity getMandatoryModule(@PathVariable final Long distributionSetTypeId,
@PathVariable final Long softwareModuleTypeId) {
@@ -257,19 +165,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(SoftwareModuleTypeMapper.toResponse(foundSmType), HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving the single optional software module
- * type in that distribution set type.
- *
- * @param distributionSetTypeId
- * of the {@link DistributionSetType}.
- * @param softwareModuleTypeId
- * of {@link SoftwareModuleType}.
- * @return Unpaged list of module types and OK in case of success.
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
- + RestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES
- + "/{softwareModuleTypeId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity getOptionalModule(@PathVariable final Long distributionSetTypeId,
@PathVariable final Long softwareModuleTypeId) {
@@ -285,17 +181,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(SoftwareModuleTypeMapper.toResponse(foundSmType), HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving the list of optional software
- * module types in that distribution set type.
- *
- * @param distributionSetTypeId
- * of the {@link DistributionSetType}.
- * @return Unpaged list of module types and OK in case of success.
- */
- @RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
- + RestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES, produces = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity getOptionalModules(@PathVariable final Long distributionSetTypeId) {
final DistributionSetType foundType = findDistributionSetTypeWithExceptionIfNotFound(distributionSetTypeId);
@@ -306,20 +192,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(rest, HttpStatus.OK);
}
- /**
- * Handles DELETE request for removing a mandatory module from the
- * {@link DistributionSetType}.
- *
- * @param distributionSetTypeId
- * of the {@link DistributionSetType}.
- * @param softwareModuleTypeId
- * of the {@link SoftwareModuleType} to remove
- *
- * @return OK if the request was successful
- */
- @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetTypeId}/"
- + RestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES
- + "/{softwareModuleTypeId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity removeMandatoryModule(@PathVariable final Long distributionSetTypeId,
@PathVariable final Long softwareModuleTypeId) {
@@ -339,20 +212,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(HttpStatus.OK);
}
- /**
- * Handles DELETE request for removing an optional module from the
- * {@link DistributionSetType}.
- *
- * @param distributionSetTypeId
- * of the {@link DistributionSetType}.
- * @param softwareModuleTypeId
- * of the {@link SoftwareModuleType} to remove
- *
- * @return OK if the request was successful
- */
- @RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetTypeId}/"
- + RestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES
- + "/{softwareModuleTypeId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity removeOptionalModule(@PathVariable final Long distributionSetTypeId,
@PathVariable final Long softwareModuleTypeId) {
final DistributionSetType foundType = findDistributionSetTypeWithExceptionIfNotFound(distributionSetTypeId);
@@ -371,21 +231,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(HttpStatus.OK);
}
- /**
- * Handles the POST request for adding a mandatory software module type to a
- * distribution set type.
- *
- * @param distributionSetTypeId
- * of the {@link DistributionSetType}.
- * @param smtId
- * of the {@link SoftwareModuleType} to add
- *
- * @return OK if the request was successful
- */
- @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetTypeId}/"
- + RestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES, consumes = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity addMandatoryModule(@PathVariable final Long distributionSetTypeId,
@RequestBody final IdRest smtId) {
@@ -400,21 +246,7 @@ public class DistributionSetTypeResource {
return new ResponseEntity<>(HttpStatus.OK);
}
- /**
- * Handles the POST request for adding an optional software module type to a
- * distribution set type.
- *
- * @param distributionSetTypeId
- * of the {@link DistributionSetType}.
- * @param smtId
- * of the {@link SoftwareModuleType} to add
- *
- * @return OK if the request was successful
- */
- @RequestMapping(method = RequestMethod.POST, value = "/{distributionSetTypeId}/"
- + RestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES, consumes = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json",
- MediaType.APPLICATION_JSON_VALUE })
+ @Override
public ResponseEntity addOptionalModule(@PathVariable final Long distributionSetTypeId,
@RequestBody final IdRest smtId) {
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DownloadArtifactResource.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DownloadArtifactResource.java
new file mode 100644
index 000000000..00f8f4756
--- /dev/null
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/DownloadArtifactResource.java
@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.resource;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
+import org.eclipse.hawkbit.repository.ArtifactManagement;
+import org.eclipse.hawkbit.repository.SoftwareManagement;
+import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
+import org.eclipse.hawkbit.repository.model.LocalArtifact;
+import org.eclipse.hawkbit.repository.model.SoftwareModule;
+import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author Jonathan Knoblauch
+ *
+ */
+@RestController
+@RequestMapping(RestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING)
+public class DownloadArtifactResource {
+
+ @Autowired
+ private SoftwareManagement softwareManagement;
+
+ @Autowired
+ private ArtifactManagement artifactManagement;
+
+ /**
+ * Handles the GET request for downloading an artifact.
+ *
+ * @param softwareModuleId
+ * of the parent SoftwareModule
+ * @param artifactId
+ * of the related LocalArtifact
+ * @param servletResponse
+ * of the servlet
+ * @param request
+ * of the client
+ *
+ * @return responseEntity with status ok if successful
+ */
+ @RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/artifacts/{artifactId}/download")
+ @ResponseBody
+ public ResponseEntity downloadArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId,
+ @PathVariable("artifactId") final Long artifactId, final HttpServletResponse servletResponse,
+ final HttpServletRequest request) {
+ final SoftwareModule module = findSoftwareModuleWithExceptionIfNotFound(softwareModuleId, artifactId);
+
+ if (null == module || !module.getLocalArtifact(artifactId).isPresent()) {
+ return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+ }
+
+ final LocalArtifact artifact = module.getLocalArtifact(artifactId).get();
+ final DbArtifact file = artifactManagement.loadLocalArtifactBinary(artifact);
+
+ final String ifMatch = request.getHeader("If-Match");
+ if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
+ return new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
+ }
+
+ return RestResourceConversionHelper.writeFileResponse(artifact, servletResponse, request, file);
+
+ }
+
+ private SoftwareModule findSoftwareModuleWithExceptionIfNotFound(final Long softwareModuleId,
+ final Long artifactId) {
+ final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
+ if (module == null) {
+ throw new EntityNotFoundException("SoftwareModule with Id {" + softwareModuleId + "} does not exist");
+ } else if (artifactId != null && !module.getLocalArtifact(artifactId).isPresent()) {
+ throw new EntityNotFoundException("Artifact with Id {" + artifactId + "} does not exist");
+ }
+ return module;
+ }
+
+}
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/RolloutMapper.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/RolloutMapper.java
index 712595638..c6be219ba 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/RolloutMapper.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/RolloutMapper.java
@@ -23,6 +23,7 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorCondit
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessAction;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
+import org.eclipse.hawkbit.rest.resource.api.RolloutRestApi;
import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutCondition.Condition;
import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutErrorAction.ErrorAction;
@@ -70,12 +71,12 @@ final class RolloutMapper {
rollout.getTotalTargetCountStatus().getTotalTargetCountByStatus(status));
}
- body.add(linkTo(methodOn(RolloutResource.class).getRollout(rollout.getId())).withRel("self"));
- body.add(linkTo(methodOn(RolloutResource.class).start(rollout.getId(), false)).withRel("start"));
- body.add(linkTo(methodOn(RolloutResource.class).start(rollout.getId(), true)).withRel("startAsync"));
- body.add(linkTo(methodOn(RolloutResource.class).pause(rollout.getId())).withRel("pause"));
- body.add(linkTo(methodOn(RolloutResource.class).resume(rollout.getId())).withRel("resume"));
- body.add(linkTo(methodOn(RolloutResource.class).getRolloutGroups(rollout.getId(),
+ body.add(linkTo(methodOn(RolloutRestApi.class).getRollout(rollout.getId())).withRel("self"));
+ body.add(linkTo(methodOn(RolloutRestApi.class).start(rollout.getId(), false)).withRel("start"));
+ body.add(linkTo(methodOn(RolloutRestApi.class).start(rollout.getId(), true)).withRel("startAsync"));
+ body.add(linkTo(methodOn(RolloutRestApi.class).pause(rollout.getId())).withRel("pause"));
+ body.add(linkTo(methodOn(RolloutRestApi.class).resume(rollout.getId())).withRel("resume"));
+ body.add(linkTo(methodOn(RolloutRestApi.class).getRolloutGroups(rollout.getId(),
Integer.parseInt(RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET),
Integer.parseInt(RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT), null, null)).withRel("groups"));
return body;
@@ -115,8 +116,9 @@ final class RolloutMapper {
body.setName(rolloutGroup.getName());
body.setRolloutGroupId(rolloutGroup.getId());
body.setStatus(rolloutGroup.getStatus().toString().toLowerCase());
- body.add(linkTo(methodOn(RolloutResource.class).getRolloutGroup(rolloutGroup.getRollout().getId(),
- rolloutGroup.getId())).withRel("self"));
+ body.add(linkTo(
+ methodOn(RolloutRestApi.class).getRolloutGroup(rolloutGroup.getRollout().getId(), rolloutGroup.getId()))
+ .withRel("self"));
return body;
}
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/RolloutResource.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/RolloutResource.java
index d72db72f9..e00d07191 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/RolloutResource.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/RolloutResource.java
@@ -27,6 +27,7 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessActi
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.rsql.RSQLUtility;
+import org.eclipse.hawkbit.rest.resource.api.RolloutRestApi;
import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutPagedList;
import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutResponseBody;
import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutRestRequestBody;
@@ -40,13 +41,8 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
@@ -54,8 +50,9 @@ import org.springframework.web.bind.annotation.RestController;
*
*/
@RestController
-@RequestMapping(RestConstants.ROLLOUT_V1_REQUEST_MAPPING)
-public class RolloutResource {
+public class RolloutResource implements RolloutRestApi {
+
+ private static final String DOES_NOT_EXIST = "} does not exist";
@Autowired
private RolloutManagement rolloutManagement;
@@ -66,31 +63,9 @@ public class RolloutResource {
@Autowired
private DistributionSetManagement distributionSetManagement;
- /**
- * Handles the GET request of retrieving all rollouts.
- *
- * @param pagingOffsetParam
- * the offset of list of rollouts for pagination, might not be
- * present in the rest request then default value will be applied
- * @param pagingLimitParam
- * the limit of the paged request, might not be present in the
- * rest request then default value will be applied
- * @param sortParam
- * the sorting parameter in the request URL, syntax
- * {@code field:direction, field:direction}
- * @param rsqlParam
- * the search parameter in the request URL, syntax
- * {@code q=name==abc}
- * @return a list of all rollouts for a defined or default page request with
- * status OK. The response is always paged. In any failure the
- * JsonResponseExceptionHandler is handling the response.
- */
- @RequestMapping(method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, "application/hal+json" })
- public ResponseEntity getRollouts(
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = RestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam,
- @RequestParam(value = RestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) {
+ @Override
+ public ResponseEntity getRollouts(final int pagingOffsetParam, final int pagingLimitParam,
+ final String sortParam, final String rsqlParam) {
final int sanitizedOffsetParam = PagingUtility.sanitizeOffsetParam(pagingOffsetParam);
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
@@ -100,50 +75,28 @@ public class RolloutResource {
final Page findModulesAll;
if (rsqlParam != null) {
- findModulesAll = rolloutManagement
+ findModulesAll = this.rolloutManagement
.findAllWithDetailedStatusByPredicate(RSQLUtility.parse(rsqlParam, RolloutFields.class), pageable);
} else {
- findModulesAll = rolloutManagement.findAll(pageable);
+ findModulesAll = this.rolloutManagement.findAll(pageable);
}
final List rest = RolloutMapper.toResponseRollout(findModulesAll.getContent());
return new ResponseEntity<>(new RolloutPagedList(rest, findModulesAll.getTotalElements()), HttpStatus.OK);
}
- /**
- * Handles the GET request of retrieving a single rollout.
- *
- * @param rolloutId
- * the ID of the rollout to retrieve
- * @return a single rollout with status OK.
- * @throws EntityNotFoundException
- * in case no rollout with the given {@code rolloutId} exists.
- */
- @RequestMapping(value = "/{rolloutId}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE,
- "application/hal+json" })
- public ResponseEntity getRollout(@PathVariable("rolloutId") final Long rolloutId) {
+ @Override
+ public ResponseEntity