Exemple #1
0
        /// <summary>
        /// The valueMap()-step yields a Map representation of the properties of an element.
        /// It is important to note that the map of a vertex maintains a list of values for each key.
        /// The map of an edge or vertex-property represents a single property (not a list).
        /// The reason is that vertices in TinkerPop leverage vertex properties which support multiple values per key.
        /// CosmosDb implementation doesn't support modulating it with .by(unfold())!
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="parameters">First parameter can be a boolean true to return id and label properties.
        ///                         Subsequent ones, if specified, will limit the response to just these properties.
        ///                         If omitted, all properties are returned</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="GremlinQueryBuilderException"></exception>
        public static GremlinQueryBuilder ValueMap(this GremlinQueryBuilder builder, params IGremlinParameter[] parameters)
        {
            // this function can only take true or false
            if (parameters.Any(p => p == null))
            {
                throw new ArgumentException("Null parameters are not allowed");
            }

            // first parameter can be string or bool
            if (parameters.Any() && !(parameters.First().TrueValue is bool) &&
                !(bool.TryParse(parameters.First().TrueValue.ToString(), out _)) &&
                !(parameters.First().TrueValue is string))
            {
                throw new GremlinQueryBuilderException(
                          $"{nameof(ValueMap)} only supports boolean or string parameters as the first parameter and '{parameters.First().TrueValue}' does not appear to be");
            }

            // subsequent parameters can only be strings
            if (parameters.Length > 1 && parameters.Skip(1).Any(p => !(p.TrueValue is string)))
            {
                throw new GremlinQueryBuilderException(
                          $"{nameof(ValueMap)} only supports strings as parameters other than the initial one that can also be a boolean");
            }

            if (parameters.Any(p => p.TrueValue is string s && (s == "id" || s == "label")))
            {
                throw new GremlinQueryBuilderException(
                          $"Property names 'id' and 'label' are not allowed. " +
                          $"If these are required, pass boolean 'true' as the first parameter to {nameof(ValueMap)}, " +
                          $"e.g. ValueMap(true) or ValueMap(true, \"PropertyName\"");
            }

            builder.AddArguments(parameters.OfType <GremlinArgument>().ToArray());
            return(builder.Add($"valueMap({parameters.Expand()})"));
        }
Exemple #2
0
        public void RejectNonStringParameters()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            Assert.Throws <GremlinQueryBuilderException>(() => builder.As(new GremlinParameter(42)));
            Assert.Throws <GremlinQueryBuilderException>(() => builder.As(new GremlinParameter(false)));
        }
        /// <summary>
        /// Predicate that checks if the incoming number is greater than or equal
        /// to the first provided number and less than the second
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="GremlinQueryBuilderException"></exception>
        public static GremlinQueryBuilder Between(this GremlinQueryBuilder builder, IGremlinParameter start, IGremlinParameter end)
        {
            if (start == null)
            {
                throw new ArgumentNullException(nameof(start));
            }
            if (end == null)
            {
                throw new ArgumentNullException(nameof(end));
            }
            if (!start.IsNumber())
            {
                throw new GremlinQueryBuilderException(
                          $"{nameof(Between)} only supports numeric parameters and '{start.TrueValue}' does not appear to conform to this");
            }
            if (!end.IsNumber())
            {
                throw new GremlinQueryBuilderException(
                          $"{nameof(Between)} only supports numeric parameters and '{end.TrueValue}' does not appear to conform to this");
            }


            builder.AddArgument(start as GremlinArgument);
            builder.AddArgument(end as GremlinArgument);
            return(builder.Add($"between({start.QueryStringValue},{end.QueryStringValue})"));
        }
Exemple #4
0
        /// <summary>
        /// It is possible to filter vertices, edges, and vertex properties based on their properties using has()-step (filter)
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="label"></param>
        /// <param name="key"></param>
        /// <param name="value">Optional value to check for. If not supplied, checks for any value for the property referenced by <paramref name="key"/></param>
        /// <returns></returns>
        public static GremlinQueryBuilder Has(this GremlinQueryBuilder builder, IGremlinParameter label, IGremlinParameter key, IGremlinParameter value)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (!(key.TrueValue is string))
            {
                throw new GremlinQueryBuilderException($"{nameof(key)} must always resolve to a string for property key and {key.TrueValue} does not");
            }
            if (label == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (!(label.TrueValue is string))
            {
                throw new GremlinQueryBuilderException($"{nameof(label)} must always resolve to a string for property key and {label.TrueValue} does not");
            }
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            builder.AddArgument(key as GremlinArgument);
            builder.AddArgument(value as GremlinArgument);
            builder.AddArgument(label as GremlinArgument);

            return(builder.Add($"has({label.QueryStringValue},{key.QueryStringValue},{value.QueryStringValue})"));
        }
        public void GeneratesCorrectSyntaxWithFunction()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.By(new GremlinQueryBuilder().AddE(new GremlinParameter("myparam")));

            Assert.Equal("by(addE('myparam'))", builder.Query);
        }
Exemple #6
0
        /// <summary>
        /// The valueMap()-step yields a Map representation of the properties of an element.
        /// It is important to note that the map of a vertex maintains a list of values for each key.
        /// The map of an edge or vertex-property represents a single property (not a list).
        /// The reason is that vertices in TinkerPop leverage vertex properties which support multiple values per key.
        /// CosmosDb implementation doesn't support modulating it with .by(unfold())!
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="properties">If specified, only these properties will be included. Cannot contain 'id' and 'label'</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="GremlinQueryBuilderException"></exception>
        public static GremlinQueryBuilder ValueMap(this GremlinQueryBuilder builder, string[] properties)
        {
            // overload for simplifying usage
            var parameters =
                (properties ?? new string[0]).Select(p => (IGremlinParameter) new GremlinParameter(p));

            return(builder.ValueMap(parameters.ToArray()));
        }
        public void GenerateCorrectSyntaxWithIntegerParameter()
        {
            var builder = new GremlinQueryBuilder();

            builder.Barrier((GremlinParameter)5);

            Assert.Equal("barrier(5)", builder.Query);
        }
        public void GenerateCorrectSyntaxForStringParameters()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.Aggregate(new GremlinParameter("myparam"));

            Assert.Equal("aggregate('myparam')", builder.Query);
        }
        public void AcceptScope()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.Aggregate(GremlinScope.Local, new GremlinParameter("myparam"));

            Assert.Equal("aggregate(local,'myparam')", builder.Query);
        }
        public void GenerateCorrectSyntaxWithParameter()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.By(new GremlinParameter("myparam"));

            Assert.Equal("by('myparam')", builder.Query);
        }
        public void GenerateCorrectSyntaxForParameterlessInvocation()
        {
            var builder = new GremlinQueryBuilder();

            builder.Barrier();

            Assert.Equal("barrier()", builder.Query);
        }
        /// <summary>
        /// There are two general ways to use select()-step.
        /// Select labeled steps within a path (as defined by as() in a traversal).
        /// Select objects out of a Map&lt;String,Object&gt; flow (i.e. a sub-map).
        /// When the set of keys or values (i.e. columns) of a path or map are needed, use select(keys)
        /// and select(values), respectively. select() can also accept a traversal that emits a key
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public static GremlinQueryBuilder Select(this GremlinQueryBuilder builder, GremlinColumnModifier columns)
        {
            if (columns == null)
            {
                throw new ArgumentNullException(nameof(columns));
            }

            return(builder.Add($"select({columns.QueryStringValue})"));
        }
Exemple #13
0
        public void GenerateCorrectSyntaxWithoutParameters()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.ValueMap();

            Assert.Equal("valueMap()", builder.Query);
            Assert.Empty(builder.Arguments);
        }
Exemple #14
0
        public void GenerateCorrectSyntaxWithSingleBoolParameter()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.ValueMap(new GremlinParameter(true));

            Assert.Equal("valueMap(true)", builder.Query);
            Assert.Empty(builder.Arguments);
        }
 /// <summary>
 /// The or()-step ensures that at least one of the provided traversals yield a result (filter).
 /// The or()-step can take an arbitrary number of traversals. At least one of the traversals must
 /// produce at least one output for the original traverser to pass to the next step.
 /// An infix notation can be used as well
 /// </summary>
 /// <param name="builder"></param>
 /// <param name="functions"></param>
 /// <returns></returns>
 /// <exception cref="GremlinQueryBuilderException"></exception>
 public static GremlinQueryBuilder Or(this GremlinQueryBuilder builder, params GremlinQueryBuilder[] functions)
 {
     if (functions == null || !functions.Any())
     {
         return(builder.Add("or()")); // for infix notation
     }
     builder.AddArguments(functions?.SelectMany(f => f.GremlinArguments).ToArray() ?? new GremlinArgument[0]);
     return(builder.Add($"or({functions.Expand()})"));
 }
Exemple #16
0
        public void GenerateCorrectSyntaxWithFunctions()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.And(new GremlinQueryBuilder().__().Out(new GremlinParameter("myparam")).HasId("test"),
                        new GremlinQueryBuilder().__().Out().Has((GremlinParameter)"name", (GremlinParameter)"MyName"));

            Assert.Equal("and(__.out('myparam').hasId('test'),__.out().has('name','MyName'))", builder.Query);
        }
Exemple #17
0
        public void GenerateCorrectSyntaxForStringParameters()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.As("a");
            builder.As((GremlinParameter)"b", (GremlinParameter)"c");

            Assert.Equal("as('a').as('b','c')", builder.Query);
        }
Exemple #18
0
        public void SupportArguments()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.As(new GremlinArgument("argumentName", "argumentValue"));

            Assert.Equal("as(argumentName)", builder.Query);
            Assert.Single(builder.Arguments);
        }
Exemple #19
0
        public void GenerateCorrectSyntaxForStringParametersAndTraversals()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.AddE(new GremlinParameter("myparam"));
            builder.AddE(new GremlinQueryBuilder().G().V("someId").Values((GremlinParameter)"label"));

            Assert.Equal("addE('myparam').addE(g.V('someId').values('label'))", builder.Query);
        }
Exemple #20
0
 public static GremlinQueryBuilder Map(this GremlinQueryBuilder builder, GremlinQueryBuilder inner)
 {
     if (inner == null)
     {
         return(builder);
     }
     builder.AddArguments(inner.GremlinArguments);
     return(builder.Add($"map({inner.Query})"));
 }
Exemple #21
0
        public void GenerateCorrectSyntaxWithArguments()
        {
            GremlinQueryBuilder builder = new GremlinQueryBuilder();

            builder.ValueMap(new GremlinArgument("bool", true), new GremlinArgument("propertyName", "prop"));

            Assert.Equal("valueMap(bool,propertyName)", builder.Query);
            Assert.Equal(2, builder.Arguments.Count);
        }
        public void HandleArguments()
        {
            var builder = new GremlinQueryBuilder();

            builder.Barrier(new GremlinArgument("five", 5));

            Assert.Equal("barrier(five)", builder.Query);
            Assert.Single(builder.Arguments);
        }
Exemple #23
0
        /// <summary>
        /// The valueMap()-step yields a Map representation of the properties of an element.
        /// It is important to note that the map of a vertex maintains a list of values for each key.
        /// The map of an edge or vertex-property represents a single property (not a list).
        /// The reason is that vertices in TinkerPop leverage vertex properties which support multiple values per key.
        /// CosmosDb implementation doesn't support modulating it with .by(unfold())!
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="includeIdAndLabel">Boolean true to return id and label properties</param>
        /// <param name="properties">If specified, only these properties will be included. Cannot contain 'id' and 'label'</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="GremlinQueryBuilderException"></exception>
        public static GremlinQueryBuilder ValueMap(this GremlinQueryBuilder builder, bool includeIdAndLabel, params string[] properties)
        {
            // overload for simplifying usage
            var parameters =
                new IGremlinParameter[] { new GremlinParameter(includeIdAndLabel) }.Concat(
                (properties ?? new string[0]).Select(p => new GremlinParameter(p)));

            return(builder.ValueMap(parameters.ToArray()));
        }
        /// <summary>
        /// Remove the traverser if its element does not have any of the ids
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        /// <exception cref="GremlinQueryBuilderException"></exception>
        public static GremlinQueryBuilder HasId(this GremlinQueryBuilder builder, params IGremlinParameter[] parameters)
        {
            if (parameters == null || !parameters.Any())
            {
                throw new GremlinQueryBuilderException($"{nameof(HasId)} requires at least one parameter in {nameof(parameters)}");
            }

            builder.AddArguments(parameters.OfType <GremlinArgument>().ToArray());
            return(builder.Add($"hasId({parameters.Expand()})"));
        }
        /// <summary>
        /// The project()-step (map) projects the current object into a Map&lt;String,Object&gt; keyed by provided labels.
        /// It is similar to <seealso cref="SelectFunction.Select(CosmosDB.Gremlin.Fluent.GremlinQueryBuilder,CosmosDB.Gremlin.Fluent.IGremlinParameter[])"/>, save that instead of retrieving and modulating historic traverser state,
        /// it modulates the current state of the traverser
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="labels"></param>
        /// <returns></returns>
        public static GremlinQueryBuilder Project(this GremlinQueryBuilder builder, params string[] labels)
        {
            if (labels == null || !labels.Any())
            {
                return(builder.Add($"project()"));
            }

            return(builder.Add(
                       $"project({labels.Select(p => (IGremlinParameter) new GremlinParameter(p)).ToArray().Expand()})"));
        }
Exemple #26
0
        /// <summary>
        /// The from()-step is not an actual step, but instead is a "step-modulator" similar to as() and by().
        /// If a step is able to accept traversals or strings then from() is the means by which they are added.
        /// The general pattern is step().from(). See <seealso cref="ToFunction.To(CosmosDB.Gremlin.Fluent.GremlinQueryBuilder,CosmosDB.Gremlin.Fluent.IGremlinParameter)"/>.
        /// The list of steps that support from()-modulation are: simplePath(), cyclicPath(), path(), and addE()
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static GremlinQueryBuilder From(this GremlinQueryBuilder builder, GremlinQueryBuilder func)
        {
            if (func == null)
            {
                throw new ArgumentNullException(nameof(func));
            }

            builder.AddArguments(func.GremlinArguments);
            return(builder.Add($"from({func.Query})"));
        }
Exemple #27
0
        /// <summary>
        /// To specify a constant value for a traverser, use the constant()-step (map).
        /// This is often useful with conditional steps like choose()-step or coalesce()-step
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static GremlinQueryBuilder Constant(this GremlinQueryBuilder builder, IGremlinParameter parameter)
        {
            if (parameter == null)
            {
                throw new ArgumentNullException(nameof(parameter));
            }

            builder.AddArgument(parameter as GremlinArgument);
            return(builder.Add($"constant({parameter.QueryStringValue})"));
        }
Exemple #28
0
        public static GremlinQueryBuilder InE(this GremlinQueryBuilder builder, params IGremlinParameter[] parameters)
        {
            if (parameters == null || !parameters.Any())
            {
                return(builder);
            }

            builder.AddArguments(parameters.OfType <GremlinArgument>().ToArray());
            return(builder.Add($"inE({parameters.Expand()})"));
        }
Exemple #29
0
        /// <summary>
        /// The optional()-step (branch/flatMap) returns the result of the specified traversal
        /// if it yields a result else it returns the calling element, i.e. the identity()
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="traversal"></param>
        /// <returns></returns>
        public static GremlinQueryBuilder Optional(this GremlinQueryBuilder builder, GremlinQueryBuilder traversal)
        {
            if (traversal == null)
            {
                throw new ArgumentNullException(nameof(traversal));
            }

            builder.AddArguments(traversal.GremlinArguments);
            return(builder.Add($"optional({traversal.Query})"));
        }
Exemple #30
0
        /// <summary>
        /// The coalesce()-step evaluates the provided traversals in order and returns the first
        /// traversal that emits at least one element
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="functions"></param>
        /// <returns></returns>
        /// <exception cref="GremlinQueryBuilderException"></exception>
        public static GremlinQueryBuilder Coalesce(this GremlinQueryBuilder builder, params GremlinQueryBuilder[] functions)
        {
            if (functions == null || !functions.Any())
            {
                throw new GremlinQueryBuilderException($"{nameof(Coalesce)} requires at least one parameter to be present in {nameof(functions)}");
            }

            builder.AddArguments(functions?.SelectMany(f => f.GremlinArguments).ToArray() ?? new GremlinArgument[0]);
            return(builder.Add($"coalesce({functions.Expand()})"));
        }