Skip to content

Commit

Permalink
Add example search query generation
Browse files Browse the repository at this point in the history
  • Loading branch information
v-yussupov committed Dec 24, 2023
1 parent 0b429bb commit 747b93c
Show file tree
Hide file tree
Showing 20 changed files with 667 additions and 280 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package org.faastener.core.controllers;

import java.net.URI;
import java.net.URISyntaxException;

import org.faastener.core.model.domain.factsources.tosca.ToscaQuery;
import org.faastener.core.services.QueryGenerationService;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -11,13 +16,44 @@
@RequestMapping("/api/search-queries")
public class SearchQueryController {

private final QueryGenerationService queryGenerationService;

public SearchQueryController(QueryGenerationService queryGenerationService) {
this.queryGenerationService = queryGenerationService;
}

@PostMapping
public ResponseEntity<String> generateQuery(@RequestBody String factSource) {
public ResponseEntity<String> generateQuery(@RequestBody ToscaQuery factSource) {
System.out.println(factSource);

return ResponseEntity
.ok()
.contentType(MediaType.APPLICATION_JSON)
.body("{ \"url\": \"http://localhost:4300/technologies\"}");
String generated = queryGenerationService.generateSearchQuery(factSource);
System.out.println(generated);

URI uri;
try {
String request = null;
if (!generated.isEmpty()) {
uri = new URI(
"http",
"localhost:8082",
"/api/technologies",
"search=" + generated,
null);

request = uri.toASCIIString();
} else {
request = "http://localhost:8082/api/technologies";
}

return ResponseEntity
.ok()
.contentType(MediaType.APPLICATION_JSON)
.body("{ \"url\": \"" + request + "\"}");
} catch (URISyntaxException e) {
e.printStackTrace();
return ResponseEntity
.badRequest()
.build();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.faastener.core.factextraction;

import java.util.List;
import java.util.Map;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.faastener.core.model.common.FilterType;
import org.faastener.core.model.domain.factsources.tosca.ToscaQuery;

@Data
@NoArgsConstructor
public class FactExtractionProcessor {
private ToscaQuery factSource;
private List<ToscaFact> extractedFacts;
private Map<String, ToscaFactMapping> factMappings = Map.of(
"faas.runtime", new ToscaFactMapping("faas.runtime", "funcRuntimes", FilterType.CONTAINS_ANY),
"faas.blobstorage", new ToscaFactMapping("faas.blobstorage", "datastoreBlob", FilterType.CONTAINS_ANY)
);

public FactExtractionProcessor(ToscaQuery factSource) {
this.factSource = factSource;
}

public void extractFacts() {
ToscaFactsExtractor extractor = new ToscaFactsExtractor();
extractedFacts = extractor.extractFactsForElement(factSource.getSelectedNode(), factSource.getTopology());
}

public String generateQueryString() {
StringBuilder sb = new StringBuilder();

for (ToscaFact fact : extractedFacts) {
if (factMappings.containsKey(fact.getFactType())) {
ToscaFactMapping mapping = factMappings.get(fact.getFactType());

sb.append(mapping.getCriterionId());
if (mapping.getFilterType() == FilterType.CONTAINS_ANY) {
sb.append("=in=(");
if ("true".equals(fact.getFactValue())) {
sb.append("*");
} else {
sb.append(fact.getFactValue());
}
sb.append(")");
sb.append(";");
}
}
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
}

return sb.toString();
}
}
14 changes: 14 additions & 0 deletions src/main/java/org/faastener/core/factextraction/ToscaFact.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.faastener.core.factextraction;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ToscaFact {
private String elementId;
private String factType;
private String factValue;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.faastener.core.factextraction;

import java.util.Optional;

import org.faastener.core.model.domain.factsources.tosca.TopologyTemplate;

@FunctionalInterface
public interface ToscaFactExtractor {
Optional<ToscaFact> extractForElement(String elementId, TopologyTemplate topologyTemplate);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.faastener.core.factextraction;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.faastener.core.model.common.FilterType;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ToscaFactMapping {
String factId;
String criterionId;
FilterType filterType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package org.faastener.core.factextraction;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import lombok.NoArgsConstructor;
import org.faastener.core.model.domain.factsources.tosca.NodeTemplate;
import org.faastener.core.model.domain.factsources.tosca.RelationshipTemplate;
import org.faastener.core.model.domain.factsources.tosca.TopologyTemplate;

@NoArgsConstructor
public class ToscaFactsExtractor {
private final Map<String, NodeTemplate> nodesMap = new HashMap<>();
private final Map<String, RelationshipTemplate> relationshipsMap = new HashMap<>();
private final List<ToscaFactExtractor> extractors = List.of(
this::extractFunctionRuntime,
this::extractObjectStorageTrigger
);

public List<ToscaFact> extractFactsForElement(String elementId, TopologyTemplate topologyTemplate) {
preprocessTopology(topologyTemplate);
List<ToscaFact> res = new ArrayList<>();

for (ToscaFactExtractor extractor : extractors) {
Optional<ToscaFact> extractionResult = extractor.extractForElement(elementId, topologyTemplate);
extractionResult.ifPresent(res::add);
}

return res;
}

private Optional<ToscaFact> extractFunctionRuntime(String functionNodeId, TopologyTemplate topologyTemplate) {
for (NodeTemplate node : topologyTemplate.getNodeTemplates()) {
if (node.getId().equals(functionNodeId)) {
Map<String, String> properties = node.getProperties();
if (properties.containsKey("runtime")) {
ToscaFact extracted = new ToscaFact();
extracted.setElementId(functionNodeId);
extracted.setFactType("faas.runtime");
extracted.setFactValue(properties.get("runtime"));

return Optional.of(extracted);
}
}
}

return Optional.empty();
}

private Optional<ToscaFact> extractObjectStorageTrigger(String functionNodeId, TopologyTemplate topologyTemplate) {
for (RelationshipTemplate rel : topologyTemplate.getRelationshipTemplates()) {
if (rel.getType().equals("{iaas.relationships.abstract}Triggers")) {
String sourceNodeId = rel.getSourceElementRef();
String targetNodeId = rel.getTargetElementRef();

if (targetNodeId.equals(functionNodeId)
&& nodesMap.containsKey(sourceNodeId)
&& nodesMap.get(sourceNodeId).getType().equals("{iaas.nodes.abstract}ObjectStorage")
) {
ToscaFact extracted = new ToscaFact();
extracted.setElementId(functionNodeId);
extracted.setFactType("faas.blobstorage");
extracted.setFactValue("*");

return Optional.of(extracted);
}
}
}

return Optional.empty();
}

private void preprocessTopology(TopologyTemplate topologyTemplate) {
for (NodeTemplate node : topologyTemplate.getNodeTemplates()) {
nodesMap.put(node.getId(), node);
}

for (RelationshipTemplate rel : topologyTemplate.getRelationshipTemplates()) {
relationshipsMap.put(rel.getId(), rel);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TRelationshipTemplate {
public String id;
public String type;
public String name;
public class Capability {
private String id;
private String name;
private String type;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.faastener.core.model.domain.factsources.tosca;

import java.util.List;
import java.util.Map;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class NodeTemplate {
private String id;
private String type;
private String name;
private Map<String, String> properties;
private List<Capability> capabilities;
private List<Requirement> requirements;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.faastener.core.model.domain.factsources.tosca;

import java.util.Map;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class RelationshipTemplate {
private String id;
private String name;
private String type;
private Map<String, String> properties;
private String sourceElementRef;
private String targetElementRef;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package org.faastener.core.model.domain.factsources.tosca;

import java.util.Map;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TNodeTemplate {
public String id;
public String type;
public String name;
public Map<String, String> properties;
public class Requirement {
private String id;
private String name;
private String node;
private String relationship;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TTopologyTemplate {
private List<TNodeTemplate> nodeTemplates;
private List<TRelationshipTemplate> relationshipTemplates;
public class TopologyTemplate {
private List<NodeTemplate> nodeTemplates;
private List<RelationshipTemplate> relationshipTemplates;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.faastener.core.model.domain.factsources.tosca;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ToscaQuery {
private String selectedNode;
private TopologyTemplate topology;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public enum RsqlSearchOperation {
IN(RSQLOperators.IN),
NOT_IN(RSQLOperators.NOT_IN);

private ComparisonOperator operator;
private final ComparisonOperator operator;

RsqlSearchOperation(final ComparisonOperator operator) {
this.operator = operator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,11 @@ public Criteria toCriteria(final String property, final ComparisonOperator opera
}*/

case IN:
return Criteria.where(keyName).in(arguments);
if (arguments != null && arguments.size() == 1 && "*".equals(arguments.get(0))) {
return Criteria.where(PREFIX + property).not().size(0);
} else {
return Criteria.where(keyName).in(arguments);
}
case NOT_IN:
return Criteria.where(keyName).nin(arguments);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.faastener.core.services;

import org.faastener.core.model.domain.factsources.tosca.ToscaQuery;

public interface QueryGenerationService {
String generateSearchQuery(ToscaQuery factSource);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.faastener.core.services;

import org.faastener.core.factextraction.FactExtractionProcessor;
import org.faastener.core.model.domain.factsources.tosca.ToscaQuery;
import org.springframework.stereotype.Service;

@Service
public class QueryGenerationServiceImpl implements QueryGenerationService {
@Override
public String generateSearchQuery(ToscaQuery factSource) {
FactExtractionProcessor processor = new FactExtractionProcessor(factSource);
processor.extractFacts();

return processor.generateQueryString();
}
}
Loading

0 comments on commit 747b93c

Please sign in to comment.