This commit is contained in:
94
modules/semrack-core/runtime/pom.xml
Normal file
94
modules/semrack-core/runtime/pom.xml
Normal file
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.codeanddata.semrack</groupId>
|
||||
<artifactId>semrack-core-parent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>semrack-core</artifactId>
|
||||
<name>Semrack Core - Runtime</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-maven-plugin</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>extension-descriptor</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-compile</id>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-extension-processor</artifactId>
|
||||
<version>${quarkus.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemdocReadContext;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface SemdocReadInterceptor {
|
||||
Uni<Void> interceptSemdocRead(SemdocReadContext context);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemdocSearchContext;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface SemdocSearchInterceptor {
|
||||
Uni<Void> interceptSemdocSearch(SemdocSearchContext context);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SearchRequest;
|
||||
import fr.codeanddata.semrack.core.models.SearchResult;
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface SemdocStorage {
|
||||
Uni<SemrackDocument> readDocument(String uid);
|
||||
Uni<SearchResult> searchDocument(SearchRequest query);
|
||||
Uni<Long> countDocuments(SearchRequest request);
|
||||
Uni<Boolean> documentsExist(SearchRequest query);
|
||||
Uni<SemrackDocument> storeDocument(SemrackDocument document);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemdocWriteContext;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface SemdocWriteInterceptor {
|
||||
Uni<Void> interceptSemdocWrite(SemdocWriteContext context);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package fr.codeanddata.semrack.core;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.enterprise.inject.spi.CDI;
|
||||
|
||||
public interface SemrackLookupExpression<T> {
|
||||
String apply(Object params);
|
||||
|
||||
default T convert(Object params) {
|
||||
return CDI.current().select(ObjectMapper.class).get().convertValue(params, new TypeReference<T>() {});
|
||||
}
|
||||
|
||||
default T convert(Object params, Class<T> clazz) {
|
||||
return CDI.current().select(ObjectMapper.class).get().convertValue(params, clazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package fr.codeanddata.semrack.core.enums;
|
||||
|
||||
public enum SemrackSortDirection {
|
||||
asc, desc
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package fr.codeanddata.semrack.core.exceptions;
|
||||
|
||||
public class SemrackException extends Exception {
|
||||
public SemrackException() {
|
||||
}
|
||||
|
||||
public SemrackException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SemrackException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public SemrackException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package fr.codeanddata.semrack.core.exceptions;
|
||||
|
||||
public class SemrackRuntimeException extends RuntimeException {
|
||||
public SemrackRuntimeException() {
|
||||
}
|
||||
|
||||
public SemrackRuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SemrackRuntimeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public SemrackRuntimeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package fr.codeanddata.semrack.core.interceptors;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import fr.codeanddata.semrack.core.SemdocWriteInterceptor;
|
||||
import fr.codeanddata.semrack.core.models.SemdocWriteContext;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ApplicationScoped
|
||||
public class AnnotateWriteInterceptor implements SemdocWriteInterceptor {
|
||||
|
||||
public static final String ANNOTATE_KEY = "annotate";
|
||||
public static final String CUSTOM_PREFIX = "custom/";
|
||||
|
||||
@Inject
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public Uni<Void> interceptSemdocWrite(SemdocWriteContext context) {
|
||||
final Map<String, Object> directives = context.getDirectives();
|
||||
|
||||
if (directives.containsKey(ANNOTATE_KEY)) {
|
||||
final Map<String, Object> annotate = objectMapper.convertValue(directives.get(ANNOTATE_KEY), new TypeReference<Map<String, Object>>() {});
|
||||
annotate.keySet().forEach(key -> context.getNextDocument().getAnnotations().put(CUSTOM_PREFIX + key, annotate.get(key)));
|
||||
}
|
||||
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package fr.codeanddata.semrack.core.interceptors;
|
||||
|
||||
import fr.codeanddata.semrack.core.SemdocWriteInterceptor;
|
||||
import fr.codeanddata.semrack.core.models.SemdocWriteContext;
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import fr.codeanddata.semrack.core.utils.UIDGenerator;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@ApplicationScoped
|
||||
public class PublishWriteInterceptor implements SemdocWriteInterceptor {
|
||||
|
||||
final String PUBLICATION_PREFIX = "publication/";
|
||||
|
||||
@Inject
|
||||
UIDGenerator uidGenerator;
|
||||
|
||||
@Override
|
||||
public Uni<Void> interceptSemdocWrite(SemdocWriteContext context) {
|
||||
final Map<String, Object> directives = context.getDirectives();
|
||||
final SemrackDocument current = context.getCurrentDocument();
|
||||
final SemrackDocument next = context.getNextDocument();
|
||||
|
||||
int version = (int) Optional.ofNullable(current)
|
||||
.map(SemrackDocument::getAnnotations)
|
||||
.map(annotations -> annotations.getOrDefault(PUBLICATION_PREFIX + "version", 0))
|
||||
.orElse(0);
|
||||
|
||||
next.getAnnotations().put(PUBLICATION_PREFIX + "reference", Optional.ofNullable(current)
|
||||
.map(SemrackDocument::getAnnotations)
|
||||
.map(annotations -> annotations.getOrDefault(PUBLICATION_PREFIX + "reference", next.getUid()))
|
||||
.orElse(next.getUid()));
|
||||
|
||||
final boolean publish = directives.getOrDefault("publish", false).equals(true);
|
||||
final boolean snapshot = directives.getOrDefault("snapshot", publish).equals(true);
|
||||
|
||||
next.getAnnotations().put(PUBLICATION_PREFIX + "publish", publish);
|
||||
next.getAnnotations().put(PUBLICATION_PREFIX + "snapshot", snapshot);
|
||||
next.getAnnotations().put(PUBLICATION_PREFIX + "version", snapshot ? version + 1 : version);
|
||||
if (snapshot && current != null) {
|
||||
next.setUid(uidGenerator.apply(next));
|
||||
}
|
||||
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.core.mappers;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import fr.codeanddata.semrack.core.models.PushDocumentRequest;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.MappingConstants;
|
||||
|
||||
@Mapper(componentModel = MappingConstants.ComponentModel.CDI)
|
||||
public abstract class SemrackDocumentMapper {
|
||||
@Mapping(source = "uid", target = "uid")
|
||||
@Mapping(source = "metadata", target = "metadata")
|
||||
abstract SemrackDocument toDocument(PushDocumentRequest document);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PaginationInfo {
|
||||
long page;
|
||||
long size;
|
||||
long total;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class PushDocumentRequest {
|
||||
/**
|
||||
* L'identifiant unique du document.
|
||||
*/
|
||||
String uid;
|
||||
|
||||
/**
|
||||
* Les directives sont les paramètres d'extensions.
|
||||
* Elles ont pour vocation de générer des actions sur les documents, comme le publish, etc...
|
||||
*/
|
||||
Map<String, Object> directives;
|
||||
|
||||
/**
|
||||
* Le contenu du document.
|
||||
*/
|
||||
Map<String, Object> metadata;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SearchRequest {
|
||||
Map<String, Object> filter;
|
||||
List<SemrackSort> sort;
|
||||
SemrackPagination paginate;
|
||||
List<String> fields;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SearchResult {
|
||||
List<SemrackDocument> documents;
|
||||
PaginationInfo pagination;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SemdocReadContext {
|
||||
|
||||
SemrackDocument currentDocument;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SemdocSearchContext {
|
||||
|
||||
Map<String, Object> search;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SemdocWriteContext {
|
||||
|
||||
/**
|
||||
* Previous stored document
|
||||
*/
|
||||
SemrackDocument currentDocument;
|
||||
|
||||
/**
|
||||
* Document to be store. It initialized with :
|
||||
* - the currentDocument uid if exists, or a new one
|
||||
* - the metadata to be persisted
|
||||
*/
|
||||
SemrackDocument nextDocument;
|
||||
|
||||
/**
|
||||
* The directives to be applied
|
||||
*/
|
||||
Map<String, Object> directives;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection(serialization = true)
|
||||
public class SemrackDocument {
|
||||
|
||||
/**
|
||||
* L'identifiant unique du document.
|
||||
*/
|
||||
String uid;
|
||||
|
||||
/**
|
||||
* Les annotations sont créées par le système, au travers des extensions. Elles sont en lecture seule.
|
||||
* Elles ont pour vocation d'aider au classement et à la recherche du document (tags, catégories, date de création, etc.).
|
||||
*/
|
||||
Map<String, Object> annotations;
|
||||
|
||||
/**
|
||||
* Le contenu du document.
|
||||
*/
|
||||
Map<String, Object> metadata;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SemrackPagination {
|
||||
Integer page;
|
||||
Integer size;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.codeanddata.semrack.core.models;
|
||||
|
||||
import fr.codeanddata.semrack.core.enums.SemrackSortDirection;
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SemrackSort {
|
||||
String field;
|
||||
SemrackSortDirection direction;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package fr.codeanddata.semrack.core.repositories;
|
||||
|
||||
import fr.codeanddata.semrack.core.SemdocStorage;
|
||||
import fr.codeanddata.semrack.core.SemdocWriteInterceptor;
|
||||
import fr.codeanddata.semrack.core.exceptions.SemrackRuntimeException;
|
||||
import fr.codeanddata.semrack.core.models.*;
|
||||
import fr.codeanddata.semrack.core.utils.UIDGenerator;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.inject.Any;
|
||||
import jakarta.enterprise.inject.Instance;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@ApplicationScoped
|
||||
public class SemdocRepository {
|
||||
|
||||
@Inject
|
||||
SemdocStorage semdocStorage;
|
||||
|
||||
@Inject
|
||||
@Any
|
||||
Instance<SemdocWriteInterceptor> writeInterceptors;
|
||||
|
||||
@Inject
|
||||
UIDGenerator uidGenerator;
|
||||
|
||||
Uni<SearchResult> searchDocument(SearchRequest query) {
|
||||
return semdocStorage.searchDocument(query);
|
||||
}
|
||||
|
||||
public Uni<SemrackDocument> pushDocument(PushDocumentRequest pushDocument) {
|
||||
return Optional.ofNullable(pushDocument.getUid()).map(semdocStorage::readDocument).orElse(Uni.createFrom().nullItem())
|
||||
.chain(currentDocument -> {
|
||||
|
||||
final SemdocWriteContext context = SemdocWriteContext.builder()
|
||||
.directives(pushDocument.getDirectives())
|
||||
.currentDocument(currentDocument)
|
||||
.nextDocument(SemrackDocument.builder()
|
||||
.uid(Optional.ofNullable(currentDocument).map(SemrackDocument::getUid).orElse(uidGenerator.apply(null)))
|
||||
.metadata(pushDocument.getMetadata())
|
||||
.annotations(new HashMap<>())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
final AtomicReference<Uni<Void>> documentUni = new AtomicReference<>(Uni.createFrom().voidItem());
|
||||
|
||||
writeInterceptors.stream().forEach(filter -> documentUni.set(documentUni.get().chain(() -> filter.interceptSemdocWrite(context))));
|
||||
return documentUni.get().chain(() -> semdocStorage.storeDocument(context.getNextDocument()));
|
||||
});
|
||||
}
|
||||
|
||||
public Uni<SemrackDocument> getOrCreate(SearchRequest query, PushDocumentRequest toCreate) {
|
||||
return searchDocument(query)
|
||||
.chain(searchResult -> {
|
||||
if (searchResult.getDocuments().isEmpty()) {
|
||||
return pushDocument(toCreate);
|
||||
} else if (searchResult.getDocuments().size() > 1) {
|
||||
throw new SemrackRuntimeException("Multiple documents found");
|
||||
} else {
|
||||
return Uni.createFrom().item(searchResult.getDocuments().getFirst());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package fr.codeanddata.semrack.core.services;
|
||||
|
||||
import fr.codeanddata.semrack.core.SemrackLookupExpression;
|
||||
import io.quarkus.runtime.StartupEvent;
|
||||
import io.smallrye.common.annotation.Identifier;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.enterprise.inject.Any;
|
||||
import jakarta.enterprise.inject.Instance;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ApplicationScoped
|
||||
public class SemrackLookupService {
|
||||
|
||||
@Inject
|
||||
@Any
|
||||
Instance<SemrackLookupExpression<?>> operators;
|
||||
|
||||
final Map<String, SemrackLookupExpression<?>> operatorsIndex = new HashMap<>();
|
||||
|
||||
void startup(@Observes StartupEvent event) {
|
||||
operators.stream()
|
||||
.filter(s -> s.getClass().getSuperclass().isAnnotationPresent(Identifier.class))
|
||||
.forEach(s -> {
|
||||
Identifier identifier = s.getClass().getSuperclass().getAnnotation(Identifier.class);
|
||||
operatorsIndex.put(identifier.value(), s);
|
||||
});
|
||||
}
|
||||
|
||||
public String lookup(Map<String, Object> lookupExpression) {
|
||||
final Set<String> lookupKeys = lookupExpression.keySet();
|
||||
if (lookupKeys.isEmpty()) {
|
||||
return "";
|
||||
} else if (lookupKeys.size() > 1) {
|
||||
throw new RuntimeException("Only one lookup expression is allowed");
|
||||
} else {
|
||||
final String lookupKey = lookupKeys.stream().findFirst().get();
|
||||
if (! operatorsIndex.containsKey(lookupKey)) {
|
||||
throw new RuntimeException("Unknown lookup expression '" + lookupKey + "'");
|
||||
} else {
|
||||
final SemrackLookupExpression<?> lookup = operatorsIndex.get(lookupKey);
|
||||
final Object lookupParams = lookupExpression.get(lookupKey);
|
||||
return lookup.apply(lookupParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package fr.codeanddata.semrack.core.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ApplicationScoped
|
||||
public class SemdocUtils {
|
||||
@Inject
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
public <T> T map(Object map, Class<T> clazz) {
|
||||
return objectMapper.convertValue(map, clazz);
|
||||
}
|
||||
|
||||
public <T> T map(Object map, TypeReference<T> typeRef) {
|
||||
return objectMapper.convertValue(map, typeRef);
|
||||
}
|
||||
|
||||
public Map<String, Object> remap(Object map) {
|
||||
return objectMapper.convertValue(map, new TypeReference<>() {});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package fr.codeanddata.semrack.core.utils;
|
||||
|
||||
import fr.codeanddata.semrack.core.models.SemrackDocument;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
@ApplicationScoped
|
||||
public class UIDGenerator implements Function<SemrackDocument, String> {
|
||||
|
||||
@Override
|
||||
public String apply(SemrackDocument semrackDocument) {
|
||||
final String uuid = UUID.randomUUID().toString();
|
||||
final LocalDateTime now = LocalDateTime.now();
|
||||
final long timestamp = now.toInstant(ZoneOffset.UTC).toEpochMilli();
|
||||
|
||||
return DigestUtils.sha256Hex(uuid + timestamp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name: Semrack Core
|
||||
#description: Do something useful.
|
||||
metadata:
|
||||
# keywords:
|
||||
# - semrack-core
|
||||
# guide: ... # To create and publish this guide, see https://github.com/quarkiverse/quarkiverse/wiki#documenting-your-extension
|
||||
# categories:
|
||||
# - "miscellaneous"
|
||||
# status: "preview"
|
||||
Reference in New Issue
Block a user