You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ze...@apache.org on 2024/08/30 12:17:18 UTC
(streampipes) 01/02: feat: First experimental version of a simplified connect API
This is an automated email from the ASF dual-hosted git repository.
zehnder pushed a commit to branch experiment-simple-connect-api
in repository https://gitbox.apache.org/repos/asf/streampipes.git
commit c7e43871e8328ffed2ebed64c01a1185b882baee
Author: Philipp Zehnder <te...@users.noreply.github.com>
AuthorDate: Tue Aug 20 08:36:31 2024 +0200
feat: First experimental version of a simplified connect API
---
.../connect/adapter/simple/SimpleAdapter.java | 44 +++++++
.../adapter/simple/SimpleConfiguration.java | 23 ++++
.../adapter/simple/SimpleEventProperty.java | 29 +++++
.../connect/adapter/simple/SimpleEventSchema.java | 26 ++++
.../model/template/PipelineElementTemplate.java | 2 +
.../rest/impl/connect/AdapterResource.java | 112 +++++++++++-----
.../rest/impl/connect/SimpleAdapterManagement.java | 142 +++++++++++++++++++++
7 files changed, 344 insertions(+), 34 deletions(-)
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleAdapter.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleAdapter.java
new file mode 100644
index 0000000000..16492f7a43
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleAdapter.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.adapter.simple;
+
+public record SimpleAdapter(
+ String name,
+ String description,
+ String appId,
+ SimpleConfiguration configuration
+) {}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleConfiguration.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleConfiguration.java
new file mode 100644
index 0000000000..399d11c671
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleConfiguration.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.adapter.simple;
+
+import java.util.Map;
+
+public record SimpleConfiguration(Map<String, String> values) {}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleEventProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleEventProperty.java
new file mode 100644
index 0000000000..00f869192f
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleEventProperty.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.adapter.simple;
+
+public record SimpleEventProperty(
+ String runtimeType,
+ String label,
+ String description,
+ String runtimeName,
+ String propertyScope,
+ String domainProperty
+) {
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleEventSchema.java b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleEventSchema.java
new file mode 100644
index 0000000000..f892061705
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/simple/SimpleEventSchema.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.connect.adapter.simple;
+
+import java.util.List;
+
+public record SimpleEventSchema(
+ List<SimpleEventProperty> properties
+) {
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/template/PipelineElementTemplate.java b/streampipes-model/src/main/java/org/apache/streampipes/model/template/PipelineElementTemplate.java
index d304b0f31e..1d398ad30f 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/template/PipelineElementTemplate.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/template/PipelineElementTemplate.java
@@ -23,6 +23,7 @@ import org.apache.streampipes.model.shared.api.Storable;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.google.gson.annotations.SerializedName;
+import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -50,6 +51,7 @@ public class PipelineElementTemplate implements Storable {
public PipelineElementTemplate() {
this.elementId = UUID.randomUUID().toString();
+ this.templateConfigs = new HashMap<>();
}
public String getTemplateName() {
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
index 6d70b8d6e6..2dd514c87b 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
@@ -18,15 +18,18 @@
package org.apache.streampipes.rest.impl.connect;
+import org.apache.streampipes.commons.exceptions.NoServiceEndpointsAvailableException;
import org.apache.streampipes.commons.exceptions.connect.AdapterException;
import org.apache.streampipes.commons.prometheus.adapter.AdapterMetricsManager;
import org.apache.streampipes.connect.management.management.AdapterMasterManagement;
import org.apache.streampipes.connect.management.management.AdapterUpdateManagement;
+import org.apache.streampipes.extensions.api.connect.exception.WorkerAdapterException;
import org.apache.streampipes.manager.pipeline.PipelineManager;
import org.apache.streampipes.model.client.user.Permission;
import org.apache.streampipes.model.client.user.Role;
import org.apache.streampipes.model.connect.adapter.AdapterDescription;
import org.apache.streampipes.model.connect.adapter.PipelineUpdateInfo;
+import org.apache.streampipes.model.connect.adapter.simple.SimpleAdapter;
import org.apache.streampipes.model.message.Message;
import org.apache.streampipes.model.message.Notifications;
import org.apache.streampipes.model.monitoring.SpLogMessage;
@@ -53,6 +56,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
+import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
@@ -91,9 +95,27 @@ public class AdapterResource extends AbstractAdapterResource<AdapterMasterManage
return ok(Notifications.success(adapterId));
}
- @PutMapping(
- produces = MediaType.APPLICATION_JSON_VALUE,
- consumes = MediaType.APPLICATION_JSON_VALUE)
+ @PostMapping(
+ path = "simpleAdapter",
+ consumes = MediaType.APPLICATION_JSON_VALUE
+ )
+ @PreAuthorize(AuthConstants.HAS_WRITE_ADAPTER_PRIVILEGE)
+ public ResponseEntity<? extends Message> addSimpleAdapter(
+ @RequestBody SimpleAdapter simpleAdapter
+ ) throws WorkerAdapterException, NoServiceEndpointsAvailableException, IOException {
+
+ var adapterDescription = new SimpleAdapterManagement().convertToAdapterDescription(simpleAdapter);
+
+ // Add adapter
+ this.addAdapter(adapterDescription);
+
+ System.out.println("Name: " + simpleAdapter.name());
+
+ return ok(Notifications.success("It works, yeah"));
+ }
+
+
+ @PutMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize(AuthConstants.HAS_WRITE_ADAPTER_PRIVILEGE)
public ResponseEntity<? extends Message> updateAdapter(@RequestBody AdapterDescription adapterDescription) {
var updateManager = new AdapterUpdateManagement(managementService);
@@ -107,13 +129,12 @@ public class AdapterResource extends AbstractAdapterResource<AdapterMasterManage
return ok(Notifications.success(adapterDescription.getElementId()));
}
- @PutMapping(
- path = "pipeline-migration-preflight",
- consumes = MediaType.APPLICATION_JSON_VALUE,
- produces = MediaType.APPLICATION_JSON_VALUE)
+ @PutMapping(path = "pipeline-migration-preflight", consumes = MediaType.APPLICATION_JSON_VALUE,
+ produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize(AuthConstants.HAS_WRITE_ADAPTER_PRIVILEGE)
public ResponseEntity<List<PipelineUpdateInfo>> performPipelineMigrationPreflight(
- @RequestBody AdapterDescription adapterDescription) {
+ @RequestBody AdapterDescription adapterDescription
+ ) {
var updateManager = new AdapterUpdateManagement(managementService);
var migrations = updateManager.checkPipelineMigrations(adapterDescription);
@@ -160,11 +181,13 @@ public class AdapterResource extends AbstractAdapterResource<AdapterMasterManage
@DeleteMapping(path = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize(AuthConstants.HAS_DELETE_ADAPTER_PRIVILEGE)
- public ResponseEntity<?> deleteAdapter(@PathVariable("id") String elementId,
- @RequestParam(value = "deleteAssociatedPipelines", defaultValue = "false")
- boolean deleteAssociatedPipelines) {
+ public ResponseEntity<?> deleteAdapter(
+ @PathVariable("id") String elementId,
+ @RequestParam(value = "deleteAssociatedPipelines", defaultValue = "false") boolean deleteAssociatedPipelines
+ ) {
List<String> pipelinesUsingAdapter = getPipelinesUsingAdapter(elementId);
- IPipelineStorage pipelineStorageAPI = StorageDispatcher.INSTANCE.getNoSqlStore().getPipelineStorageAPI();
+ IPipelineStorage pipelineStorageAPI = StorageDispatcher.INSTANCE.getNoSqlStore()
+ .getPipelineStorageAPI();
if (pipelinesUsingAdapter.isEmpty()) {
try {
@@ -175,22 +198,41 @@ public class AdapterResource extends AbstractAdapterResource<AdapterMasterManage
return ok(Notifications.error(e.getMessage()));
}
} else if (!deleteAssociatedPipelines) {
- List<String> namesOfPipelinesUsingAdapter =
- pipelinesUsingAdapter.stream().map(pipelineId -> pipelineStorageAPI.getElementById(pipelineId).getName())
- .collect(
- Collectors.toList());
- return ResponseEntity.status(HttpStatus.SC_CONFLICT).body(String.join(", ", namesOfPipelinesUsingAdapter));
+ List<String> namesOfPipelinesUsingAdapter = pipelinesUsingAdapter
+ .stream()
+ .map(pipelineId -> pipelineStorageAPI.getElementById(
+ pipelineId)
+ .getName())
+ .collect(Collectors.toList());
+ return ResponseEntity.status(HttpStatus.SC_CONFLICT)
+ .body(String.join(", ", namesOfPipelinesUsingAdapter));
} else {
PermissionResourceManager permissionResourceManager = new PermissionResourceManager();
// find out the names of pipelines that have an owner and the owner is not the current user
- List<String> namesOfPipelinesNotOwnedByUser = pipelinesUsingAdapter.stream().filter(pipelineId ->
- !permissionResourceManager.findForObjectId(pipelineId).stream().findFirst().map(Permission::getOwnerSid)
- // if a pipeline has no owner, pretend the owner is the user so the user can delete it
- .orElse(this.getAuthenticatedUserSid()).equals(this.getAuthenticatedUserSid()))
- .map(pipelineId -> pipelineStorageAPI.getElementById(pipelineId).getName()).collect(Collectors.toList());
- boolean isAdmin = SecurityContextHolder.getContext().getAuthentication().getAuthorities().stream()
- .anyMatch(r -> r.getAuthority().equals(
- Role.ROLE_ADMIN.name()));
+ List<String> namesOfPipelinesNotOwnedByUser = pipelinesUsingAdapter
+ .stream()
+ .filter(pipelineId -> !permissionResourceManager.findForObjectId(
+ pipelineId)
+ .stream()
+ .findFirst()
+ .map(
+ Permission::getOwnerSid)
+ // if a pipeline has no owner, pretend the owner
+ // is the user so the user can delete it
+ .orElse(
+ this.getAuthenticatedUserSid())
+ .equals(
+ this.getAuthenticatedUserSid()))
+ .map(pipelineId -> pipelineStorageAPI.getElementById(
+ pipelineId)
+ .getName())
+ .collect(Collectors.toList());
+ boolean isAdmin = SecurityContextHolder.getContext()
+ .getAuthentication()
+ .getAuthorities()
+ .stream()
+ .anyMatch(r -> r.getAuthority()
+ .equals(Role.ROLE_ADMIN.name()));
// if the user is admin or owns all pipelines using this adapter,
// the user can delete all associated pipelines and this adapter
if (isAdmin || namesOfPipelinesNotOwnedByUser.isEmpty()) {
@@ -200,15 +242,17 @@ public class AdapterResource extends AbstractAdapterResource<AdapterMasterManage
PipelineManager.deletePipeline(pipelineId);
}
managementService.deleteAdapter(elementId);
- return ok(Notifications.success(
- "Adapter with id: " + elementId + " and all pipelines using the adapter are deleted."));
+ return ok(Notifications.success("Adapter with id: " + elementId
+ + " and all pipelines using the adapter are deleted."));
} catch (Exception e) {
- LOG.error("Error while deleting adapter with id " + elementId + " and all pipelines using the adapter", e);
+ LOG.error("Error while deleting adapter with id "
+ + elementId + " and all pipelines using the adapter", e);
return ok(Notifications.error(e.getMessage()));
}
} else {
// otherwise, hint the user the names of pipelines using the adapter but not owned by the user
- return ResponseEntity.status(HttpStatus.SC_CONFLICT).body(String.join(", ", namesOfPipelinesNotOwnedByUser));
+ return ResponseEntity.status(HttpStatus.SC_CONFLICT)
+ .body(String.join(", ", namesOfPipelinesNotOwnedByUser));
}
}
}
@@ -220,7 +264,8 @@ public class AdapterResource extends AbstractAdapterResource<AdapterMasterManage
return ok(managementService.getAllAdapterInstances());
} catch (AdapterException e) {
LOG.error("Error while getting all adapters", e);
- return ResponseEntity.status(500).build();
+ return ResponseEntity.status(500)
+ .build();
}
}
@@ -229,10 +274,9 @@ public class AdapterResource extends AbstractAdapterResource<AdapterMasterManage
}
private List<String> getPipelinesUsingAdapter(String adapterId) {
- return StorageDispatcher.INSTANCE
- .getNoSqlStore()
- .getPipelineStorageAPI()
- .getPipelinesUsingAdapter(adapterId);
+ return StorageDispatcher.INSTANCE.getNoSqlStore()
+ .getPipelineStorageAPI()
+ .getPipelinesUsingAdapter(adapterId);
}
}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/SimpleAdapterManagement.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/SimpleAdapterManagement.java
new file mode 100644
index 0000000000..1084a11993
--- /dev/null
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/SimpleAdapterManagement.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.rest.impl.connect;
+
+import org.apache.streampipes.commons.exceptions.NoServiceEndpointsAvailableException;
+import org.apache.streampipes.connect.management.management.GuessManagement;
+import org.apache.streampipes.extensions.api.connect.exception.WorkerAdapterException;
+import org.apache.streampipes.manager.template.AdapterTemplateHandler;
+import org.apache.streampipes.model.connect.adapter.AdapterDescription;
+import org.apache.streampipes.model.connect.adapter.simple.SimpleAdapter;
+import org.apache.streampipes.model.connect.adapter.simple.SimpleEventProperty;
+import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+import org.apache.streampipes.model.template.PipelineElementTemplate;
+import org.apache.streampipes.model.template.PipelineElementTemplateConfig;
+import org.apache.streampipes.storage.api.IAdapterStorage;
+import org.apache.streampipes.storage.couchdb.CouchDbStorageManager;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+
+public class SimpleAdapterManagement {
+ public AdapterDescription convertToAdapterDescription(SimpleAdapter simpleAdapter)
+ throws WorkerAdapterException,
+ NoServiceEndpointsAvailableException,
+ IOException {
+
+ // Get the adapter description from the registed adapters
+ var adapterDescription = findAdapterDescription(simpleAdapter.appId());
+
+ // Set basic configurations
+ setNameAndDescription(adapterDescription, simpleAdapter);
+
+ // Fill out user configurations
+ applyUserConfiguraition(adapterDescription, simpleAdapter);
+
+ // Set event schema
+ addEventSchema(adapterDescription);
+
+ return adapterDescription;
+ }
+
+ private void addEventSchema(
+ AdapterDescription adapterDescription) throws WorkerAdapterException, NoServiceEndpointsAvailableException, IOException {
+
+ var guessManagement = new GuessManagement();
+ GuessSchema result = guessManagement.guessSchema(adapterDescription);
+ adapterDescription.getDataStream().setEventSchema(result.getEventSchema());
+
+// var eventProperties = simpleAdapter.eventSchema()
+// .properties()
+// .stream()
+// .map(simpleEventProperty -> simpleEventPropertyToEventProperty(
+// simpleEventProperty))
+// .toList();
+//
+// var eventSchema = new EventSchema(eventProperties);
+// adapterDescription.getDataStream()
+// .setEventSchema(eventSchema);
+ }
+
+
+ private EventProperty simpleEventPropertyToEventProperty(
+ SimpleEventProperty simpleEventProperty
+ ) {
+ var eventPropertyPrimitive = new EventPropertyPrimitive();
+ eventPropertyPrimitive.setRuntimeType(simpleEventProperty.runtimeType());
+ eventPropertyPrimitive.setLabel(simpleEventProperty.label());
+ eventPropertyPrimitive.setDescription(simpleEventProperty.description());
+ eventPropertyPrimitive.setRuntimeName(simpleEventProperty.runtimeName());
+ eventPropertyPrimitive.setPropertyScope(simpleEventProperty.propertyScope());
+ if (simpleEventProperty.domainProperty() != null && !simpleEventProperty.domainProperty()
+ .equals("")) {
+ var url = URI.create(simpleEventProperty.domainProperty());
+ eventPropertyPrimitive.setDomainProperties(List.of(url));
+ }
+
+ return eventPropertyPrimitive;
+ }
+
+ private void applyUserConfiguraition(
+ AdapterDescription adapterDescription,
+ SimpleAdapter simpleAdapter
+ ) {
+
+ var adapterTemplate = new PipelineElementTemplate();
+ var templateConfigs = simpleAdapter.configuration();
+
+ templateConfigs.values()
+ .forEach((key, value) -> {
+ PipelineElementTemplateConfig config = new PipelineElementTemplateConfig();
+ // Assuming PipelineElementTemplateConfig has a method to set key and value
+ config.setValue(value);
+ adapterTemplate.getTemplateConfigs()
+ .put(key, config);
+ });
+
+ new AdapterTemplateHandler(
+ adapterTemplate, adapterDescription,
+ false
+ )
+ .applyTemplateOnPipelineElement();
+ }
+
+ private void setNameAndDescription(
+ AdapterDescription adapterDescription,
+ SimpleAdapter simpleAdapter
+ ) {
+ adapterDescription.setName(simpleAdapter.name());
+ adapterDescription.setDescription(simpleAdapter.description());
+ }
+
+ private AdapterDescription findAdapterDescription(String appId) {
+ IAdapterStorage adapterStorage = CouchDbStorageManager.INSTANCE.getAdapterDescriptionStorage();
+ return adapterStorage.findAll()
+ .stream()
+ .filter(desc -> desc.getAppId()
+ .equals(appId))
+ .findFirst()
+ .get();
+
+ }
+
+}