This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new b539aa646 feat(#2376): Add find endpoint to generic storage API (#2377)
b539aa646 is described below
commit b539aa646600697b15621977fce544101315ca1c
Author: Dominik Riemer <[email protected]>
AuthorDate: Thu Dec 28 13:19:44 2023 +0100
feat(#2376): Add find endpoint to generic storage API (#2377)
---
.../rest/impl/GenericStorageResource.java | 20 +++++++-
.../streampipes/storage/api/IGenericStorage.java | 2 +
.../storage/couchdb/impl/GenericStorageImpl.java | 23 ++++++++-
.../src/lib/apis/generic-storage.service.ts | 31 +++++++-----
.../src/lib/query/generic-storage-query-builder.ts | 58 ++++++++++++++++++++++
.../platform-services/src/public-api.ts | 1 +
6 files changed, 119 insertions(+), 16 deletions(-)
diff --git
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java
index 6efef1df9..9f74d7205 100644
---
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java
+++
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java
@@ -79,6 +79,22 @@ public class GenericStorageResource extends
AbstractAuthGuardedRestResource {
}
}
+ @PostMapping(
+ path = "/{appDocName}/find",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ @PreAuthorize(AuthConstants.HAS_WRITE_GENERIC_STORAGE_PRIVILEGE)
+ public ResponseEntity<List<Map<String, Object>>>
find(@PathVariable(APP_DOC_NAME) String appDocName,
+ @RequestBody
Map<String, Object> query) {
+ try {
+ var docs = getGenericStorage().find(appDocName, query);
+ return ok(docs);
+ } catch (IOException e) {
+ LOG.error("Could not connect to storage", e);
+ throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e);
+ }
+ }
+
@GetMapping(path = "/{appDocName}/{id}", produces =
MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize(AuthConstants.HAS_READ_GENERIC_STORAGE_PRIVILEGE)
public ResponseEntity<Map<String, Object>>
getCategory(@PathVariable(APP_DOC_NAME) String appDocName,
@@ -98,8 +114,8 @@ public class GenericStorageResource extends
AbstractAuthGuardedRestResource {
consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize(AuthConstants.HAS_WRITE_GENERIC_STORAGE_PRIVILEGE)
public ResponseEntity<Map<String, Object>>
update(@PathVariable(APP_DOC_NAME) String appDocName,
- @PathVariable("id") String documentId,
- @RequestBody String document) {
+ @PathVariable("id") String
documentId,
+ @RequestBody String
document) {
try {
Map<String, Object> obj = getGenericStorage().update(documentId,
document);
return ok(obj);
diff --git
a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
index 528e8c93b..e9d9208f9 100644
---
a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
+++
b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
@@ -28,6 +28,8 @@ public interface IGenericStorage {
List<Map<String, Object>> findAll(String type) throws IOException;
+ List<Map<String, Object>> find(String appDocType, Map<String, Object> query)
throws IOException;
+
Map<String, Object> findOne(String id) throws IOException;
Map<String, Object> create(String payload) throws IOException;
diff --git
a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java
b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java
index 6d5884ee4..f8f6942ef 100644
---
a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java
+++
b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java
@@ -41,8 +41,11 @@ public class GenericStorageImpl implements IGenericStorage {
private static final String ID = "id";
private static final String SLASH = "/";
+ private static final String DOCS_KEY = "docs";
+
private final TypeReference<Map<String, Object>> typeRef = new
TypeReference<>() {
};
+
private final ObjectMapper mapper;
public GenericStorageImpl() {
@@ -68,6 +71,22 @@ public class GenericStorageImpl implements IGenericStorage {
return result;
}
+ @Override
+ public List<Map<String, Object>> find(String appDocType,
+ Map<String, Object> query) throws
IOException {
+ var request = Utils.postRequest(
+ getDatabaseRoute() + "/_find",
+ mapper.writeValueAsString(query)
+ );
+ Content content = executeAndReturnContent(request);
+ var responseObj = deserialize(content.asString(StandardCharsets.UTF_8));
+ if (responseObj != null & responseObj.containsKey("docs")) {
+ return (List<Map<String, Object>>) responseObj.get(DOCS_KEY);
+ } else {
+ return List.of();
+ }
+ }
+
@Override
public Map<String, Object> findOne(String id) throws IOException {
return this.queryDocuments(getDatabaseRoute() + SLASH + id);
@@ -110,7 +129,7 @@ public class GenericStorageImpl implements IGenericStorage {
byte[] payload,
String rev) throws IOException {
Request req = Utils.putRequest(
- getDatabaseRoute() + SLASH + docId + SLASH + attachmentName +
"?rev=" + rev, payload, contentType
+ getDatabaseRoute() + SLASH + docId + SLASH + attachmentName + "?rev="
+ rev, payload, contentType
);
executeAndReturnContent(req);
}
@@ -118,7 +137,7 @@ public class GenericStorageImpl implements IGenericStorage {
@Override
public GenericStorageAttachment findAttachment(String docId, String
attachmentName) throws IOException {
Request req = Utils.getRequest(getDatabaseRoute() + SLASH + docId + SLASH
+ attachmentName);
- Content content = executeAndReturnContent(req);
+ Content content = executeAndReturnContent(req);
return new GenericStorageAttachment(content.getType().getMimeType(),
content.asBytes());
}
diff --git
a/ui/projects/streampipes/platform-services/src/lib/apis/generic-storage.service.ts
b/ui/projects/streampipes/platform-services/src/lib/apis/generic-storage.service.ts
index f4b1ccb28..6f18f3f3a 100644
---
a/ui/projects/streampipes/platform-services/src/lib/apis/generic-storage.service.ts
+++
b/ui/projects/streampipes/platform-services/src/lib/apis/generic-storage.service.ts
@@ -30,37 +30,44 @@ export class GenericStorageService {
private platformServicesCommons: PlatformServicesCommons,
) {}
- createDocument(appDocName: string, document: any): Observable<any> {
- return this.http.post(this.getAppDocPath(appDocName), document);
+ createDocument(appDocType: string, document: any): Observable<any> {
+ return this.http.post(this.getAppDocPath(appDocType), document);
}
- getAllDocuments(appDocName: string): Observable<any> {
- return this.http.get(this.getAppDocPath(appDocName));
+ getAllDocuments(appDocType: string): Observable<any> {
+ return this.http.get(this.getAppDocPath(appDocType));
}
- getDocument(appDocName: string, documentId: string): Observable<any> {
- return
this.http.get(`${this.getAppDocPath(appDocName)}/${documentId}`);
+ findDocuments(
+ appDocType: string,
+ query: Record<string, any>,
+ ): Observable<any> {
+ return this.http.post(`${this.getAppDocPath(appDocType)}/find`, query);
+ }
+
+ getDocument(appDocType: string, documentId: string): Observable<any> {
+ return
this.http.get(`${this.getAppDocPath(appDocType)}/${documentId}`);
}
- updateDocument(appDocName: string, document: any): Observable<any> {
+ updateDocument(appDocType: string, document: any): Observable<any> {
return this.http.put(
- `${this.getAppDocPath(appDocName)}/${document._id}`,
+ `${this.getAppDocPath(appDocType)}/${document._id}`,
document,
);
}
deleteDocument(
- appDocName: string,
+ appDocType: string,
documentId: string,
rev: string,
): Observable<any> {
return this.http.delete(
- `${this.getAppDocPath(appDocName)}/${documentId}/${rev}`,
+ `${this.getAppDocPath(appDocType)}/${documentId}/${rev}`,
);
}
- private getAppDocPath(appDocName: string): string {
- return this.genericStorageBasePath + '/' + appDocName;
+ private getAppDocPath(appDocType: string): string {
+ return this.genericStorageBasePath + '/' + appDocType;
}
private get genericStorageBasePath() {
diff --git
a/ui/projects/streampipes/platform-services/src/lib/query/generic-storage-query-builder.ts
b/ui/projects/streampipes/platform-services/src/lib/query/generic-storage-query-builder.ts
new file mode 100644
index 000000000..98c8b1f5f
--- /dev/null
+++
b/ui/projects/streampipes/platform-services/src/lib/query/generic-storage-query-builder.ts
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ *
+ */
+
+export class GenericStorageQueryBuilder {
+ private query: Record<string, any> = {};
+ private selectors: Record<string, any> = {};
+
+ static create(appDocType: string): GenericStorageQueryBuilder {
+ return new GenericStorageQueryBuilder(appDocType);
+ }
+
+ constructor(appDocType: string) {
+ this.addSelector('appDocType', { $eq: appDocType });
+ }
+
+ public withFields(fields: string[]): GenericStorageQueryBuilder {
+ this.query.fields = fields;
+ return this;
+ }
+
+ public withLimit(limit: number): GenericStorageQueryBuilder {
+ this.query.limit = limit;
+ return this;
+ }
+
+ public withSkip(skip: number): GenericStorageQueryBuilder {
+ this.query.skip = skip;
+ return this;
+ }
+
+ public addSelector(
+ key: string,
+ condition: Record<string, any>,
+ ): GenericStorageQueryBuilder {
+ this.selectors[key] = condition;
+ return this;
+ }
+
+ public build() {
+ this.query.selector = this.selectors;
+ return this.query;
+ }
+}
diff --git a/ui/projects/streampipes/platform-services/src/public-api.ts
b/ui/projects/streampipes/platform-services/src/public-api.ts
index 433e6bffe..d5cb1d61f 100644
--- a/ui/projects/streampipes/platform-services/src/public-api.ts
+++ b/ui/projects/streampipes/platform-services/src/public-api.ts
@@ -62,6 +62,7 @@ export * from './lib/model/gen/streampipes-model';
export * from './lib/model/datalake/data-lake-query-config.model';
export * from './lib/query/DatalakeQueryParameterBuilder';
export * from './lib/query/data-view-query-generator.service';
+export * from './lib/query/generic-storage-query-builder';
export * from './lib/model/user/user.model';
export * from './lib/model/assets/asset.model';