Skip to content

Commit

Permalink
feat(document): document deserialization & serialization (#3066)
Browse files Browse the repository at this point in the history
* wip

(cherry picked from commit a57e940)

* wip

(cherry picked from commit 5634aea)

* prepare end-to-end draft

(cherry picked from commit 92ec79f)

* prepare end-to-end draft

(cherry picked from commit 5a808bd)

* rework deserializers

(cherry picked from commit 0b0a558)

* incorporate feedback, move jackson code into a separate module

* clean up accidental change

* naming adjustments

* lint

* remove extra dollar sign

* remove extra dollar sign
  • Loading branch information
chillleader committed Aug 29, 2024
1 parent 694c204 commit 1ed03da
Show file tree
Hide file tree
Showing 46 changed files with 1,649 additions and 211 deletions.
6 changes: 6 additions & 0 deletions connector-runtime/connector-runtime-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,11 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
<scope>test</scope>
</dependency>

</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.camunda.connector.document.jackson;
package io.camunda.connector.runtime.core.document;

import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.module.SimpleModule;
import io.camunda.connector.api.document.Document;
import io.camunda.connector.api.document.operation.DocumentOperation;
import io.camunda.connector.api.document.operation.DocumentOperationExecutor;

public class JacksonModuleDocument extends SimpleModule {
public class AggregatingOperationExecutor implements DocumentOperationExecutor {

@Override
public String getModuleName() {
return "JacksonModuleDocument";
}
public AggregatingOperationExecutor() {}

@Override
public Version version() {
// TODO: get version from pom.xml
return new Version(0, 1, 0, null, "io.camunda", "jackson-datatype-document");
public boolean matches(DocumentOperation operationReference) {
return true;
}

@Override
public void setupModule(SetupContext context) {
addDeserializer(Document.class, new DocumentDeserializer());
addSerializer(Document.class, new DocumentSerializer());
super.setupModule(context);
public Object execute(DocumentOperation operationReference, Document document) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; 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 io.camunda.connector.runtime.core.document;

import io.camunda.connector.api.document.Document;
import io.camunda.connector.api.document.DocumentMetadata;
import io.camunda.connector.api.document.DocumentReference;
import io.camunda.connector.api.document.DocumentReference.CamundaDocumentReference;
import io.camunda.connector.api.document.store.CamundaDocumentStore;
import java.io.InputStream;
import java.util.Base64;

public class CamundaDocument implements Document {

private final DocumentMetadata metadata;
private final CamundaDocumentReference reference;
private final CamundaDocumentStore documentStore;

public CamundaDocument(
DocumentMetadata metadata,
CamundaDocumentReference reference,
CamundaDocumentStore documentStore) {
this.metadata = metadata;
this.reference = reference;
this.documentStore = documentStore;
}

@Override
public DocumentMetadata metadata() {
return metadata;
}

@Override
public String asBase64() {
return Base64.getEncoder().encodeToString(asByteArray());
}

@Override
public InputStream asInputStream() {
return documentStore.getDocumentContent(reference);
}

@Override
public byte[] asByteArray() {
try {
return documentStore.getDocumentContent(reference).readAllBytes();
} catch (Exception e) {
throw new RuntimeException("Failed to read document content", e);
}
}

@Override
public DocumentReference reference() {
return reference;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; 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 io.camunda.connector.runtime.core.document;

import io.camunda.connector.api.document.DocumentMetadata;
import io.camunda.connector.api.document.DocumentReference;

public record CamundaDocumentReferenceImpl(
String storeId, String documentId, DocumentMetadata metadata)
implements DocumentReference.CamundaDocumentReference {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; 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 io.camunda.connector.runtime.core.document;

import io.camunda.connector.api.document.Document;
import io.camunda.connector.api.document.DocumentFactory;
import io.camunda.connector.api.document.DocumentReference;
import io.camunda.connector.api.document.DocumentReference.CamundaDocumentReference;
import io.camunda.connector.api.document.DocumentReference.ExternalDocumentReference;
import io.camunda.connector.api.document.store.CamundaDocumentStore;
import io.camunda.connector.api.document.store.DocumentCreationRequest;

public class DocumentFactoryImpl implements DocumentFactory {

private final CamundaDocumentStore documentStore;

public DocumentFactoryImpl(CamundaDocumentStore documentStore) {
this.documentStore = documentStore;
}

@Override
public Document resolve(DocumentReference reference) {
return switch (reference) {
case CamundaDocumentReference camundaDocumentReference -> new CamundaDocument(
camundaDocumentReference.metadata(), camundaDocumentReference, documentStore);
case ExternalDocumentReference ignored -> throw new IllegalArgumentException(
"External document references are not yet supported: " + reference.getClass());
default -> throw new IllegalArgumentException("Unsupported document reference: " + reference);
};
}

@Override
public Document create(DocumentCreationRequest request) {
var reference = documentStore.createDocument(request);
return resolve(reference);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; 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 io.camunda.connector.runtime.core.document;

import io.camunda.connector.api.document.DocumentMetadata;
import io.camunda.connector.api.document.DocumentReference.CamundaDocumentReference;
import io.camunda.connector.api.document.store.CamundaDocumentStore;
import io.camunda.connector.api.document.store.DocumentCreationRequest;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class InMemoryDocumentStore implements CamundaDocumentStore {

public static final String STORE_ID = "in-memory";

private final Map<String, byte[]> documents = new HashMap<>();

@Override
public CamundaDocumentReference createDocument(DocumentCreationRequest request) {
final String id =
request.documentId() != null ? request.documentId() : UUID.randomUUID().toString();
final DocumentMetadata metadata = request.metadata();
final byte[] content;
try (InputStream contentStream = request.content()) {
content = contentStream.readAllBytes();
} catch (Exception e) {
throw new RuntimeException("Failed to read document content", e);
}
documents.put(id, content);
return new CamundaDocumentReferenceImpl(STORE_ID, id, metadata);
}

@Override
public InputStream getDocumentContent(CamundaDocumentReference reference) {
var content = documents.get(reference.documentId());
if (content == null) {
throw new RuntimeException("Document not found: " + reference.documentId());
}
return new ByteArrayInputStream(content);
}

@Override
public void deleteDocument(CamundaDocumentReference reference) {
documents.remove(reference.documentId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; 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 io.camunda.connector.runtime.core.document.operation;

import io.camunda.connector.api.document.Document;
import io.camunda.connector.api.document.operation.DocumentOperation;
import io.camunda.connector.api.document.operation.DocumentOperationExecutor;

public class Base64Operation implements DocumentOperationExecutor {

@Override
public boolean matches(DocumentOperation operationReference) {
return false;
}

@Override
public Object execute(DocumentOperation operationReference, Document document) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.EvictingQueue;
import io.camunda.connector.api.document.DocumentFactory;
import io.camunda.connector.api.inbound.InboundConnectorContext;
import io.camunda.connector.api.inbound.InboundConnectorExecutable;
import io.camunda.connector.api.inbound.InboundIntermediateConnectorContext;
Expand All @@ -35,18 +36,21 @@ public class DefaultInboundConnectorContextFactory implements InboundConnectorCo
private final SecretProviderAggregator secretProviderAggregator;
private final ValidationProvider validationProvider;
private final OperateClientAdapter operateClientAdapter;
private final DocumentFactory documentFactory;

public DefaultInboundConnectorContextFactory(
final ObjectMapper mapper,
final InboundCorrelationHandler correlationHandler,
final SecretProviderAggregator secretProviderAggregator,
final ValidationProvider validationProvider,
final OperateClientAdapter operateClientAdapter) {
final OperateClientAdapter operateClientAdapter,
final DocumentFactory documentFactory) {
this.objectMapper = mapper;
this.correlationHandler = correlationHandler;
this.secretProviderAggregator = secretProviderAggregator;
this.validationProvider = validationProvider;
this.operateClientAdapter = operateClientAdapter;
this.documentFactory = documentFactory;
}

@Override
Expand All @@ -60,6 +64,7 @@ public <T extends InboundConnectorExecutable<?>> InboundConnectorContext createC
new InboundConnectorContextImpl(
secretProviderAggregator,
validationProvider,
documentFactory,
connectorDetails,
correlationHandler,
cancellationCallback,
Expand Down
Loading

0 comments on commit 1ed03da

Please sign in to comment.