You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by sh...@apache.org on 2019/05/28 18:09:12 UTC
[unomi] 01/02: findSegments and findEvents fields now work
partially,
retrieving partially built results. Filters are not yet doing anything.
This is an automated email from the ASF dual-hosted git repository.
shuber pushed a commit to branch UNOMI-180-CXS-GRAPHQLAPI
in repository https://gitbox.apache.org/repos/asf/unomi.git
commit e420ae329a0d3eec511630de472667eb0bdb1788
Author: Serge Huber <sh...@jahia.com>
AuthorDate: Tue May 28 15:36:29 2019 +0200
findSegments and findEvents fields now work partially, retrieving partially built results. Filters are not yet doing anything.
---
graphql/README.md | 77 ++++++++++
.../unomi/graphql/internal/CDPSDLServletImpl.java | 156 +++++++++++++++++----
.../src/main/resources/cdp-schema.graphqls | 8 +-
3 files changed, 213 insertions(+), 28 deletions(-)
diff --git a/graphql/README.md b/graphql/README.md
new file mode 100644
index 0000000..94e8714
--- /dev/null
+++ b/graphql/README.md
@@ -0,0 +1,77 @@
+Apache Unomi GraphQL API
+========================
+
+Install
+-------
+
+Installing GraphQL feature:
+
+ feature:repo-add mvn:org.apache.unomi/cdp-graphql-feature/1.4.0-SNAPSHOT/xml/features
+ feature:install cdp-graphql-feature
+
+GraphQL Endpoint
+----------------
+
+You can then access the GraphQL endpoint at the following URL:
+
+ http://localhost:8181/sdlgraphql
+
+Query example
+-------------
+
+operation::
+
+ query findEvents($filter: CDP_EventFilterInput) {
+ cdp {
+ findEvents(filter: $filter) {
+ pageInfo {
+ hasNextPage
+ hasPreviousPage
+ }
+ edges {
+ cursor
+ node {
+ id
+ cdp_profileID {
+ client {
+ id
+ title
+ }
+ id
+ uri
+ }
+ __typename
+ }
+ }
+ }
+ }
+ }
+
+variables::
+
+ {
+ "filter": {
+ "cdp_profileID_equals": ""
+ }
+ }
+
+Segment query operation:
+
+ query findSegments($segmentFilter: CDP_SegmentFilterInput) {
+ cdp {
+ findSegments(filter: $segmentFilter) {
+ edges {
+ node {
+ id
+ name
+ view {
+ name
+ }
+ profiles {
+ profileIDs
+ }
+ }
+ }
+ }
+ }
+ }
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/internal/CDPSDLServletImpl.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/internal/CDPSDLServletImpl.java
index 68be5b9..2deae05 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/internal/CDPSDLServletImpl.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/internal/CDPSDLServletImpl.java
@@ -32,7 +32,15 @@ import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.Metadata;
+import org.apache.unomi.api.PartialList;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.query.Query;
+import org.apache.unomi.api.segments.Segment;
+import org.apache.unomi.api.services.DefinitionsService;
import org.apache.unomi.api.services.EventService;
+import org.apache.unomi.api.services.SegmentService;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@@ -45,7 +53,9 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
@Component(
@@ -59,6 +69,9 @@ public class CDPSDLServletImpl extends HttpServlet {
private GraphQL graphQL;
private EventService eventService;
+ private DefinitionsService definitionsService;
+ private SegmentService segmentService;
+
@Activate
void activate(BundleContext bundleContext) {
@@ -70,6 +83,16 @@ public class CDPSDLServletImpl extends HttpServlet {
this.eventService = eventService;
}
+ @Reference
+ public void setDefinitionService(DefinitionsService definitionService) {
+ this.definitionsService = definitionService;
+ }
+
+ @Reference
+ public void setSegmentService(SegmentService segmentService) {
+ this.segmentService = segmentService;
+ }
+
RuntimeWiring buildRuntimeWiring() {
GraphQLScalarType emptyTypeWorkAroundScalarType = GraphQLScalarType.newScalar()
@@ -125,7 +148,7 @@ public class CDPSDLServletImpl extends HttpServlet {
.typeResolver(new TypeResolver() {
@Override
public GraphQLObjectType getType(TypeResolutionEnvironment env) {
- return null;
+ return env.getSchema().getObjectType("CDP_ProfileUpdateEvent");
}
}))
.type("CDP_ProfileInterface", typeWiring -> typeWiring
@@ -142,37 +165,116 @@ public class CDPSDLServletImpl extends HttpServlet {
return null;
}
}))
- .type("CDP_Query", typeWiring -> typeWiring.dataFetcher("findEvents", new DataFetcher() {
- @Override
- public Object get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception {
- // PartialList<Event> events = eventService.searchEvents(condition, offset, size);
- return null;
+ .type("Query", typeWiring -> typeWiring.dataFetcher("cdp", dataFetchingEnvironment -> "CDP"))
+ .type("CDP_Query", typeWiring -> typeWiring
+ .dataFetcher("findEvents", dataFetchingEnvironment -> {
+ Map<String,Object> arguments = dataFetchingEnvironment.getArguments();
+ Integer size = (Integer) arguments.get("first");
+ if (size == null) {
+ size = 10;
+ }
+ String after = (String) arguments.get("after");
+ if (after == null) {
+ after = "0";
+ }
+ int offset = Integer.parseInt(after);
+ Object filter = arguments.get("filter");
+ Condition condition = eventFilter2Condition(filter);
+ PartialList<Event> events = eventService.searchEvents(condition, offset, size);
+ Map<String,Object> eventConnection = new HashMap<>();
+ List<Map<String,Object>> eventEdges = new ArrayList<>();
+ for (Event event : events.getList()) {
+ Map<String,Object> eventEdge = new HashMap<>();
+ Map<String,Object> eventNode = new HashMap<>();
+ eventNode.put("id", event.getItemId());
+ eventNode.put("__unomiEventType", event.getEventType());
+ eventNode.put("cdp_profileID", getCDPProfileID(event.getProfileId()));
+ eventEdge.put("node", eventNode);
+ eventEdge.put("cursor", event.getItemId());
+ eventEdges.add(eventEdge);
}
+ eventConnection.put("edges", eventEdges);
+ Map<String,Object> pageInfo = new HashMap<>();
+ pageInfo.put("hasPreviousPage", false);
+ pageInfo.put("hasNextPage", events.getTotalSize() > events.getList().size());
+ eventConnection.put("pageInfo", pageInfo);
+ return eventConnection;
+ })
+ .dataFetcher("findSegments", dataFetchingEnvironment -> {
+ Map<String,Object> arguments = dataFetchingEnvironment.getArguments();
+ Integer size = (Integer) arguments.get("first");
+ if (size == null) {
+ size = 10;
+ }
+ String after = (String) arguments.get("after");
+ if (after == null) {
+ after = "0";
+ }
+ int offset = Integer.parseInt(after);
+ Object filter = arguments.get("filter");
+ Condition condition = eventFilter2Condition(filter);
+
+ Map<String,Object> segmentConnection = new HashMap<>();
+ Query query = new Query();
+ query.setCondition(condition);
+ query.setLimit(size);
+ query.setOffset(offset);
+ // query.setSortby(sortBy);
+ PartialList<Metadata> segmentMetadatas = segmentService.getSegmentMetadatas(query);
+ List<Map<String,Object>> segmentEdges = new ArrayList<>();
+ for (Metadata segmentMetadata : segmentMetadatas.getList()) {
+ Map<String,Object> segment = new HashMap<>();
+ segment.put("id", segmentMetadata.getId());
+ segment.put("name", segmentMetadata.getName());
+ Map<String,Object> segmentView = new HashMap<>();
+ segmentView.put("name", segmentMetadata.getScope());
+ segment.put("view", segmentView);
+ Segment unomiSegment = segmentService.getSegmentDefinition(segmentMetadata.getId());
+ Condition segmentCondition = unomiSegment.getCondition();
+ segment.put("profiles", segmentConditionToProfileFilter(segmentCondition));
+ Map<String,Object> segmentEdge = new HashMap<>();
+ segmentEdge.put("node", segment);
+ segmentEdge.put("cursor", segmentMetadata.getId());
+ segmentEdges.add(segmentEdge);
+ }
+ segmentConnection.put("edges", segmentEdges);
+ Map<String,Object> pageInfo = new HashMap<>();
+ pageInfo.put("hasPreviousPage", false);
+ pageInfo.put("hasNextPage", segmentMetadatas.getTotalSize() > segmentMetadatas.getList().size());
+ segmentConnection.put("pageInfo", pageInfo);
+ return segmentConnection;
}))
- // this uses builder function lambda syntax
- /*
- .type("QueryType", typeWiring -> typeWiring
- .dataFetcher("hero", new StaticDataFetcher(StarWarsData.getArtoo()))
- .dataFetcher("human", StarWarsData.getHumanDataFetcher())
- .dataFetcher("droid", StarWarsData.getDroidDataFetcher())
- )
- .type("Human", typeWiring -> typeWiring
- .dataFetcher("friends", StarWarsData.getFriendsDataFetcher())
- )
- // you can use builder syntax if you don't like the lambda syntax
- .type("Droid", typeWiring -> typeWiring
- .dataFetcher("friends", StarWarsData.getFriendsDataFetcher())
- )
- // or full builder syntax if that takes your fancy
- .type(
- newTypeWiring("Character")
- .typeResolver(StarWarsData.getCharacterTypeResolver())
- .build()
- )
- */
.build();
}
+ private Map<String, Object> segmentConditionToProfileFilter(Condition segmentCondition) {
+ Map<String,Object> profileFilter = new HashMap<>();
+ // profileFilter.put("profileIDs", new ArrayList<String>());
+ return profileFilter;
+ }
+
+ private Map<String,Object> getCDPProfileID(String profileId) {
+ Map<String,Object> cdpProfileID = new HashMap<>();
+ Map<String,Object> client = getCDPClient(profileId);
+ cdpProfileID.put("client", client);
+ cdpProfileID.put("id", profileId);
+ cdpProfileID.put("uri", "cdp_profile:" + client.get("id") + "/" + profileId);
+ return cdpProfileID;
+ }
+
+ private Map<String,Object> getCDPClient(String profileId) {
+ Map<String,Object> cdpClient = new HashMap<>();
+ cdpClient.put("id", "unomi");
+ cdpClient.put("title", "Default Unomi client");
+ return cdpClient;
+ }
+
+ private Condition eventFilter2Condition(Object filter) {
+ // todo implement transformation to proper event conditions
+ Condition matchAllCondition = new Condition(definitionsService.getConditionType("matchAllCondition"));
+ return matchAllCondition;
+ }
+
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
diff --git a/graphql/cxs-impl/src/main/resources/cdp-schema.graphqls b/graphql/cxs-impl/src/main/resources/cdp-schema.graphqls
index 6e178a6..1e71cbe 100644
--- a/graphql/cxs-impl/src/main/resources/cdp-schema.graphqls
+++ b/graphql/cxs-impl/src/main/resources/cdp-schema.graphqls
@@ -971,4 +971,10 @@ Uses RFC-3339 representation, for example 16:39:57-08:00, see
https://github.com/graphql-java/graphql-java-extended-scalars for example
implementation
"""
-scalar Time
\ No newline at end of file
+scalar Time
+
+schema {
+ query : Query
+ mutation : Mutation
+ subscription : Subscription
+}
\ No newline at end of file