Skip to content

Commit

Permalink
rework deserializers
Browse files Browse the repository at this point in the history
  • Loading branch information
chillleader committed Aug 7, 2024
1 parent 5a808bd commit 0b0a558
Show file tree
Hide file tree
Showing 19 changed files with 742 additions and 249 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
@@ -0,0 +1,66 @@
/*
* 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 java.io.ByteArrayInputStream;
import java.io.InputStream;
public record DocumentCreationRequest(
DocumentMetadata metadata,
InputStream content,
String documentId,
String storeId) {
public static BuilderStepMetadata from(InputStream content) {
return new BuilderStepMetadata(content);
}
public static BuilderStepMetadata from(byte[] content) {
return new BuilderStepMetadata(new ByteArrayInputStream(content));
}
public static class BuilderStepMetadata {
private final InputStream content;
public BuilderStepMetadata(InputStream content) {
this.content = content;
}
public BuilderStepDocumentId metadata(DocumentMetadata metadata) {
return new BuilderStepDocumentId(metadata, content);
}
public BuilderStepDocument
}
public static class BuilderStepDocumentId {
private final DocumentMetadata metadata;
private final InputStream content;
public BuilderStepDocumentId(DocumentMetadata metadata, InputStream content) {
this.metadata = metadata;
this.content = content;
}
public BuilderStepStoreId documentId(String documentId) {
return new BuilderStepStoreId(metadata, content, documentId);
}
}
}
*/
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

public interface DocumentStore {

// TODO: support document ID, store ID
DocumentReference createDocument(DocumentMetadata metadata, byte[] content);

DocumentReference createDocument(DocumentMetadata metadata, InputStream content);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,31 @@
*/
package io.camunda.connector.runtime.core.document.jackson;

import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import io.camunda.connector.api.document.DocumentReference;
import io.camunda.connector.runtime.core.document.DocumentFactory;
import io.camunda.connector.runtime.core.document.DocumentOperationExecutor;
import java.io.IOException;

public class DocumentAnnotationIntrospector extends JacksonAnnotationIntrospector {
public class ByteArrayDocumentDeserializer extends DocumentDeserializerBase<byte[]> {

private final DocumentFactory documentFactory;
private final DocumentOperationExecutor operationExecutor;
public ByteArrayDocumentDeserializer(
DocumentOperationExecutor operationExecutor, DocumentFactory documentFactory) {
super(operationExecutor, documentFactory);
}

@Override
public byte[] deserializeDocumentReference(
DocumentReference reference, DeserializationContext ctx) throws IOException {

public DocumentAnnotationIntrospector(
DocumentFactory factory, DocumentOperationExecutor operationExecutor) {
this.documentFactory = factory;
this.operationExecutor = operationExecutor;
ensureNoOperation(reference);
var document = createDocument(reference);
return document.asByteArray();
}

@Override
public Object findDeserializer(Annotated a) {
DocumentAware ann = _findAnnotation(a, DocumentAware.class);
if (ann != null) {
return new DocumentAwareObjectDeserializer(ann.lazy(), documentFactory, operationExecutor);
}
return super.findDeserializer(a);
public byte[] fallback(JsonNode node, DeserializationContext ctx) throws IOException {
return ctx.readTreeAsValue(node, byte[].class);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.jackson;

import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import io.camunda.connector.api.document.Document;
import io.camunda.connector.api.document.DocumentReference;
import io.camunda.connector.runtime.core.document.DocumentFactory;
import io.camunda.connector.runtime.core.document.DocumentOperationExecutor;
import java.io.IOException;

public class DocumentDeserializer extends DocumentDeserializerBase<Document> {

public DocumentDeserializer(
DocumentOperationExecutor operationExecutor, DocumentFactory documentFactory) {
super(operationExecutor, documentFactory);
}

@Override
public Document deserializeDocumentReference(
DocumentReference reference, DeserializationContext ctx) {

ensureNoOperation(reference);
return createDocument(reference);
}

@Override
public Document fallback(JsonNode node, DeserializationContext ctx) throws IOException {
var fieldName = ctx.getParser().currentName();
throw new IllegalArgumentException(
fieldName
+ ": unsupported document format. Expected a document reference, got: "
+ fieldName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* 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.jackson;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import io.camunda.connector.api.document.Document;
import io.camunda.connector.api.document.DocumentOperation;
import io.camunda.connector.api.document.DocumentOperationResult;
import io.camunda.connector.api.document.DocumentReference;
import io.camunda.connector.api.document.DocumentSource.ReferenceDocumentSource;
import io.camunda.connector.runtime.core.document.DocumentFactory;
import io.camunda.connector.runtime.core.document.DocumentOperationExecutor;
import java.io.IOException;

public abstract class DocumentDeserializerBase<T> extends JsonDeserializer<T> {

protected final DocumentOperationExecutor operationExecutor;
protected final DocumentFactory documentFactory;

public DocumentDeserializerBase(
DocumentOperationExecutor operationExecutor, DocumentFactory documentFactory) {
this.operationExecutor = operationExecutor;
this.documentFactory = documentFactory;
}

@Override
public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {

JsonNode node = p.readValueAsTree();
if (node == null || node.isNull()) {
return null;
}
if (isDocumentReference(node)) {
var reference = toReference(node, ctxt);
return deserializeDocumentReference(reference, ctxt);
}
return fallback(node, ctxt);
}

/** Will be invoked when the deserializable data is a document reference. */
public abstract T deserializeDocumentReference(
DocumentReference reference, DeserializationContext ctx) throws IOException;

/**
* Will be invoked when the deserializable data is not a document reference. Deserializers should
* implement this method to provide a fallback behavior.
*/
public abstract T fallback(JsonNode node, DeserializationContext ctx) throws IOException;

protected boolean isDocumentReference(JsonNode node) {
return node.has(DocumentReference.DISCRIMINATOR_KEY);
}

protected DocumentReference toReference(JsonNode node, DeserializationContext ctx)
throws IOException {

if (!isDocumentReference(node)) {
throw new IllegalArgumentException(
"Unsupported document format. Expected a document reference, got: " + node);
}
return ctx.readTreeAsValue(node, DocumentReference.class);
}

protected void ensureNoOperation(DocumentReference reference) {
if (reference.operation().isPresent()) {
throw new IllegalArgumentException(
"Unsupported document format. Expected a document reference without operation, got: "
+ reference);
}
}

protected Document createDocument(DocumentReference reference) {
return documentFactory.from(new ReferenceDocumentSource(reference)).build();
}

protected DocumentOperationResult<?> deserializeOperation(
DocumentReference reference, DocumentOperation operation) {
return () -> operationExecutor.execute(operation, createDocument(reference));
}
}
Loading

0 comments on commit 0b0a558

Please sign in to comment.