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/25 19:06:47 UTC

[unomi] 05/20: UNOMI-180 Implement CXS GraphQL API - We now have basic filtering generation for event types working !

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 bbfc5e6b195a1b6f7c5f22b2dbc3e2247c641c05
Author: Serge Huber <sh...@apache.org>
AuthorDate: Mon May 28 15:07:00 2018 +0200

    UNOMI-180 Implement CXS GraphQL API
    - We now have basic filtering generation for event types working !
    
    Signed-off-by: Serge Huber <sh...@apache.org>
---
 .../apache/unomi/graphql/CXSDateFilterInput.java   |  30 +++
 .../graphql/CXSEventOccurrenceFilterInput.java     |  33 +++
 .../apache/unomi/graphql/CXSGeoDistanceInput.java  |  28 ++
 .../apache/unomi/graphql/CXSGeoDistanceUnit.java   |  23 ++
 .../org/apache/unomi/graphql/CXSGeoPointInput.java |  26 ++
 .../org/apache/unomi/graphql/CXSOrderByInput.java  |  28 ++
 .../org/apache/unomi/graphql/CXSSortOrder.java     |  23 ++
 .../java/org/apache/unomi/graphql/PageInfo.java    |  28 ++
 .../graphql/internal/CXSGraphQLProviderImpl.java   | 285 ++++++++++++++++++++-
 9 files changed, 496 insertions(+), 8 deletions(-)

diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSDateFilterInput.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSDateFilterInput.java
new file mode 100644
index 0000000..f92759e
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSDateFilterInput.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); 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 org.apache.unomi.graphql;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+
+public class CXSDateFilterInput {
+    @GraphQLField
+    public long after;
+    @GraphQLField
+    public boolean includeAfter;
+    @GraphQLField
+    public long before;
+    @GraphQLField
+    public boolean includeBefore;
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSEventOccurrenceFilterInput.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSEventOccurrenceFilterInput.java
new file mode 100644
index 0000000..83d23da
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSEventOccurrenceFilterInput.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); 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 org.apache.unomi.graphql;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+
+public class CXSEventOccurrenceFilterInput {
+
+    @GraphQLField
+    public String eventId;
+    @GraphQLField
+    public String beforeTime;
+    @GraphQLField
+    public String afterTime;
+    @GraphQLField
+    public String betweenTime;
+    @GraphQLField
+    public int count;
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSGeoDistanceInput.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSGeoDistanceInput.java
new file mode 100644
index 0000000..59d0fa9
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSGeoDistanceInput.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); 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 org.apache.unomi.graphql;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+
+public class CXSGeoDistanceInput {
+    @GraphQLField
+    public CXSGeoPoint center;
+    @GraphQLField
+    public CXSGeoDistanceUnit unit;
+    @GraphQLField
+    public float distance;
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSGeoDistanceUnit.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSGeoDistanceUnit.java
new file mode 100644
index 0000000..5db4d3e
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSGeoDistanceUnit.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); 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 org.apache.unomi.graphql;
+
+public enum CXSGeoDistanceUnit {
+    METERS,
+    KILOMETERS,
+    MILES
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSGeoPointInput.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSGeoPointInput.java
new file mode 100644
index 0000000..19b0297
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSGeoPointInput.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); 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 org.apache.unomi.graphql;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+
+public class CXSGeoPointInput {
+    @GraphQLField
+    public float longitude;
+    @GraphQLField
+    public float latitude;
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSOrderByInput.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSOrderByInput.java
new file mode 100644
index 0000000..a0221d2
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSOrderByInput.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); 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 org.apache.unomi.graphql;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+
+public class CXSOrderByInput {
+
+    @GraphQLField
+    public String fieldName;
+
+    @GraphQLField
+    public CXSSortOrder sortOrder;
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSSortOrder.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSSortOrder.java
new file mode 100644
index 0000000..ca0f3bd
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/CXSSortOrder.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); 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 org.apache.unomi.graphql;
+
+public enum CXSSortOrder {
+    ASC,
+    DESC,
+    UNSPECIFIED
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/PageInfo.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/PageInfo.java
new file mode 100644
index 0000000..a49d774
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/PageInfo.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); 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 org.apache.unomi.graphql;
+
+import graphql.annotations.annotationTypes.GraphQLField;
+
+public class PageInfo {
+
+    @GraphQLField
+    public boolean hasPreviousPage;
+    @GraphQLField
+    public boolean hasNextPage;
+
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/internal/CXSGraphQLProviderImpl.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/internal/CXSGraphQLProviderImpl.java
index 6d5a792..2c7a0b4 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/internal/CXSGraphQLProviderImpl.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/internal/CXSGraphQLProviderImpl.java
@@ -58,28 +58,229 @@ public class CXSGraphQLProviderImpl implements CXSGraphQLProvider, GraphQLQueryP
 
     private void updateGraphQLTypes() {
 
+        registeredOutputTypes.put(PageInfo.class.getName(), annotationsComponent.getOutputTypeProcessor().getOutputTypeOrRef(PageInfo.class, container));
+
         registeredOutputTypes.put(CXSGeoPoint.class.getName(), annotationsComponent.getOutputTypeProcessor().getOutputTypeOrRef(CXSGeoPoint.class, container));
         registeredOutputTypes.put(CXSSetPropertyType.class.getName(),annotationsComponent.getOutputTypeProcessor().getOutputTypeOrRef(CXSSetPropertyType.class, container));
         registeredOutputTypes.put(CXSEventType.class.getName(), annotationsComponent.getOutputTypeProcessor().getOutputTypeOrRef(CXSEventType.class, container));
 
+        registeredInputTypes.put(CXSGeoDistanceInput.class.getName(), annotationsComponent.getInputTypeProcessor().getInputTypeOrRef(CXSGeoDistanceInput.class, container));
+        registeredInputTypes.put(CXSDateFilterInput.class.getName(), annotationsComponent.getInputTypeProcessor().getInputTypeOrRef(CXSDateFilterInput.class, container));
         registeredInputTypes.put(CXSEventTypeInput.class.getName(), annotationsComponent.getInputTypeProcessor().getInputTypeOrRef(CXSEventTypeInput.class, container));
+        registeredInputTypes.put(CXSOrderByInput.class.getName(), annotationsComponent.getInputTypeProcessor().getInputTypeOrRef(CXSOrderByInput.class, container));
         registeredInputTypes.put("CXS_EventInput", buildCXSEventInputType());
+        registeredInputTypes.put(CXSEventOccurrenceFilterInput.class.getName(), annotationsComponent.getInputTypeProcessor().getInputTypeOrRef(CXSEventOccurrenceFilterInput.class, container));
+        registeredInputTypes.put("CXS_EventPropertiesFilterInput", buildCXSEventPropertiesFilterInput());
+        registeredInputTypes.put("CXS_EventFilterInput", buildCXSEventFilterInputType());
 
         registeredOutputTypes.put("CXS_EventProperties", buildCXSEventPropertiesOutputType());
 
-        /*
-        GraphQLObjectInfoRetriever graphQLObjectInfoRetriever = new GraphQLObjectInfoRetriever();
-        GraphQLInputObjectType cxsEventTypeInput = new InputObjectBuilder(graphQLObjectInfoRetriever, new ParentalSearch(graphQLObjectInfoRetriever),
-                new BreadthFirstSearch(graphQLObjectInfoRetriever), new GraphQLFieldRetriever()).
-                getInputObjectBuilder(CXSEventTypeInput.class, GraphQLAnnotations.getInstance().getContainer()).build();
-        registeredInputTypes.put(CXSEventTypeInput.class.getName(), cxsEventTypeInput);
-        */
-
         registeredOutputTypes.put("CXS_Event", buildCXSEventOutputType());
+        registeredOutputTypes.put("CXS_EventEdge", buildCXSEventEdgeOutputType());
+        registeredOutputTypes.put("CXS_EventConnection", buildCXSEventConnectionOutputType());
         registeredOutputTypes.put("CXS_Query", buildCXSQueryOutputType());
         registeredOutputTypes.put("CXS_Mutation", buildCXSMutationOutputType());
     }
 
+    private GraphQLOutputType buildCXSEventEdgeOutputType() {
+        return newObject()
+                .name("CXS_EventEdge")
+                .description("The Relay edge type for the CXS_Event output type")
+                .field(newFieldDefinition()
+                        .name("node")
+                        .type(registeredOutputTypes.get("CXS_Event"))
+                )
+                .field(newFieldDefinition()
+                        .name("cursor")
+                        .type(GraphQLString)
+                )
+                .build();
+    }
+
+    private GraphQLOutputType buildCXSEventConnectionOutputType() {
+        return newObject()
+                .name("CXS_EventConnection")
+                .description("The Relay connection type for the CXS_Event output type")
+                .field(newFieldDefinition()
+                        .name("edges")
+                        .type(new GraphQLList(registeredOutputTypes.get("CXS_EventEdge")))
+                )
+                .field(newFieldDefinition()
+                        .name("pageInfo")
+                        .type(new GraphQLList(registeredOutputTypes.get(PageInfo.class.getName())))
+                )
+                .build();
+    }
+
+    private GraphQLInputType buildCXSEventPropertiesFilterInput() {
+        GraphQLInputObjectType.Builder cxsEventPropertiesFilterInput = newInputObject()
+                .name("CXS_EventPropertiesFilterInput")
+                .description("Filter conditions for each event types and built-in properties");
+
+        generateEventPropertiesFilters(cxsEventPropertiesFilterInput);
+        generateEventTypesFilters(cxsEventPropertiesFilterInput);
+
+        return cxsEventPropertiesFilterInput.build();
+    }
+
+
+    private void generateEventPropertiesFilters(GraphQLInputObjectType.Builder cxsEventPropertiesFilterInput) {
+        addIdentityFilters("id", cxsEventPropertiesFilterInput);
+        addIdentityFilters("sourceId", cxsEventPropertiesFilterInput);
+        addIdentityFilters("clientId", cxsEventPropertiesFilterInput);
+        addIdentityFilters("profileId", cxsEventPropertiesFilterInput);
+        addDistanceFilters("location", cxsEventPropertiesFilterInput);
+        addDateFilters("timestamp", cxsEventPropertiesFilterInput);
+    }
+
+    private void generateEventTypesFilters(GraphQLInputObjectType.Builder cxsEventPropertiesFilterInput) {
+        for (Map.Entry<String,CXSEventType> eventTypeEntry : eventTypes.entrySet()) {
+            addSetFilters(eventTypeEntry.getKey(), eventTypeEntry.getValue().properties, cxsEventPropertiesFilterInput);
+        }
+    }
+
+    private void addSetFilters(String eventTypeName, List<CXSPropertyType> properties, GraphQLInputObjectType.Builder inputTypeBuilder) {
+        GraphQLInputObjectType.Builder eventTypeFilterInput = newInputObject()
+                .name(eventTypeName + "FilterInput")
+                .description("Auto-generated filter input type for event type " + eventTypeName);
+
+        for (CXSPropertyType cxsPropertyType : properties) {
+            if (cxsPropertyType instanceof CXSIdentifierPropertyType) {
+                addIdentityFilters(cxsPropertyType.name, eventTypeFilterInput);
+            } else if (cxsPropertyType instanceof CXSStringPropertyType) {
+                addStringFilters(cxsPropertyType.name, eventTypeFilterInput);
+            } else if (cxsPropertyType instanceof CXSBooleanPropertyType) {
+                addBooleanFilters(cxsPropertyType.name, eventTypeFilterInput);
+            } else if (cxsPropertyType instanceof CXSIntPropertyType) {
+                addIntegerFilters(cxsPropertyType.name, eventTypeFilterInput);
+            } else if (cxsPropertyType instanceof CXSFloatPropertyType) {
+                addFloatFilters(cxsPropertyType.name, eventTypeFilterInput);
+            } else if (cxsPropertyType instanceof CXSGeoPointPropertyType) {
+                addDistanceFilters(cxsPropertyType.name, eventTypeFilterInput);
+            } else if (cxsPropertyType instanceof CXSDatePropertyType) {
+                addDateFilters(cxsPropertyType.name, eventTypeFilterInput);
+            } else if (cxsPropertyType instanceof CXSSetPropertyType) {
+                addSetFilters(cxsPropertyType.name, ((CXSSetPropertyType) cxsPropertyType).properties, eventTypeFilterInput);
+            }
+        }
+
+        registeredInputTypes.put(eventTypeName + "FilterInput", eventTypeFilterInput.build());
+
+        inputTypeBuilder.field(newInputObjectField()
+                .name(eventTypeName)
+                .type(registeredInputTypes.get(eventTypeName + "FilterInput"))
+        );
+
+    }
+
+    private void addIdentityFilters(String propertyName, GraphQLInputObjectType.Builder inputTypeBuilder) {
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_equals")
+                .type(GraphQLString)
+        );
+    }
+
+    private void addStringFilters(String propertyName, GraphQLInputObjectType.Builder inputTypeBuilder) {
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_equals")
+                .type(GraphQLString)
+        );
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_regexp")
+                .type(GraphQLString)
+        );
+    }
+
+    private void addBooleanFilters(String propertyName, GraphQLInputObjectType.Builder inputTypeBuilder) {
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_equals")
+                .type(GraphQLBoolean)
+        );
+    }
+
+    private void addIntegerFilters(String propertyName, GraphQLInputObjectType.Builder inputTypeBuilder) {
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_equals")
+                .type(GraphQLInt)
+        );
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_gt")
+                .type(GraphQLInt)
+        );
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_gte")
+                .type(GraphQLInt)
+        );
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_lt")
+                .type(GraphQLInt)
+        );
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_lte")
+                .type(GraphQLInt)
+        );
+    }
+
+    private void addFloatFilters(String propertyName, GraphQLInputObjectType.Builder inputTypeBuilder) {
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_equals")
+                .type(GraphQLFloat)
+        );
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_gt")
+                .type(GraphQLFloat)
+        );
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_gte")
+                .type(GraphQLFloat)
+        );
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_lt")
+                .type(GraphQLFloat)
+        );
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_lte")
+                .type(GraphQLFloat)
+        );
+    }
+
+    private void addDistanceFilters(String propertyName, GraphQLInputObjectType.Builder inputTypeBuilder) {
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_distance")
+                .type(registeredInputTypes.get(CXSGeoDistanceInput.class.getName()))
+        );
+    }
+
+    private void addDateFilters(String propertyName, GraphQLInputObjectType.Builder inputTypeBuilder) {
+        inputTypeBuilder.field(newInputObjectField()
+                .name(propertyName + "_between")
+                .type(registeredInputTypes.get(CXSDateFilterInput.class.getName()))
+        );
+    }
+
+    private GraphQLInputType buildCXSEventFilterInputType() {
+        GraphQLInputObjectType.Builder cxsEventFilterInputType = newInputObject()
+                .name("CXS_EventFilterInput")
+                .description("Filter conditions for each event types and built-in properties")
+                .field(newInputObjectField()
+                        .name("and")
+                        .type(new GraphQLList(new GraphQLTypeReference("CXS_EventFilterInput")))
+                )
+                .field(newInputObjectField()
+                        .name("or")
+                        .type(new GraphQLList(new GraphQLTypeReference("CXS_EventFilterInput")))
+                )
+                .field(newInputObjectField()
+                        .name("properties")
+                        .type(registeredInputTypes.get("CXS_EventPropertiesFilterInput"))
+                )
+                .field(newInputObjectField()
+                        .name("eventOccurrence")
+                        .type(registeredInputTypes.get(CXSEventOccurrenceFilterInput.class.getName()))
+                );
+        return cxsEventFilterInputType.build();
+    }
+
     private GraphQLInputType buildCXSEventInputType() {
         GraphQLInputObjectType.Builder cxsEventInputType = newInputObject()
                 .name("CXS_EventInput")
@@ -201,6 +402,74 @@ public class CXSGraphQLProviderImpl implements CXSGraphQLProvider, GraphQLQueryP
                         .name("getEvent")
                         .description("Retrieves a specific event")
                 )
+                .field(newFieldDefinition()
+                        .type(new GraphQLList(registeredOutputTypes.get("CXS_EventConnection")))
+                        .name("findEvents")
+                        .argument(newArgument()
+                                .name("filter")
+                                .type(registeredInputTypes.get("CXS_EventFilterInput"))
+                        )
+                        .argument(newArgument()
+                                .name("orderBy")
+                                .type(registeredInputTypes.get(CXSOrderByInput.class.getName()))
+                        )
+                        .argument(newArgument()
+                                .name("first")
+                                .type(GraphQLInt)
+                                .description("Number of objects to retrieve starting at the after cursor position")
+                        )
+                        .argument(newArgument()
+                                .name("after")
+                                .type(GraphQLString)
+                                .description("Starting cursor location to retrieve the object from")
+                        )
+                        .argument(newArgument()
+                                .name("last")
+                                .type(GraphQLInt)
+                                .description("Number of objects to retrieve end at the before cursor position")
+                        )
+                        .argument(newArgument()
+                                .name("before")
+                                .type(GraphQLString)
+                                .description("End cursor location to retrieve the object from")
+                        )
+                        .description("Retrieves the events that match the specified filters")
+                )
+                /*
+                .field(newFieldDefinition()
+                        .type(new GraphQLList(registeredOutputTypes.get("CXS_ProfileConnection")))
+                        .name("findProfiles")
+                        .argument(newArgument()
+                                .name("filter")
+                                .type(registeredInputTypes.get("CXS_ProfileFilterInput"))
+                        )
+                        .argument(newArgument()
+                                .name("orderBy")
+                                .type(registeredInputTypes.get(CXSOrderByInput.class.getName()))
+                        )
+                        .argument(newArgument()
+                                .name("first")
+                                .type(GraphQLInt)
+                                .description("Number of objects to retrieve starting at the after cursor position")
+                        )
+                        .argument(newArgument()
+                                .name("after")
+                                .type(GraphQLString)
+                                .description("Starting cursor location to retrieve the object from")
+                        )
+                        .argument(newArgument()
+                                .name("last")
+                                .type(GraphQLInt)
+                                .description("Number of objects to retrieve end at the before cursor position")
+                        )
+                        .argument(newArgument()
+                                .name("before")
+                                .type(GraphQLString)
+                                .description("End cursor location to retrieve the object from")
+                        )
+                        .description("Retrieves the profiles that match the specified profiles")
+                )
+                */
                 .build();
     }