Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
atlas
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
dataplatform
atlas
Commits
69af0ae7
Commit
69af0ae7
authored
Oct 27, 2016
by
Jeff Hagelberg
Committed by
Dave Kantor
Oct 27, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ATLAS-1195 Clean up DSL Translation (jnhagelb via dkantor)
parent
aa15cd0a
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
2341 additions
and
475 deletions
+2341
-475
AbstractGroovyExpression.java
...ava/org/apache/atlas/groovy/AbstractGroovyExpression.java
+36
-0
ArithmeticExpression.java
...in/java/org/apache/atlas/groovy/ArithmeticExpression.java
+59
-0
BinaryExpression.java
...c/main/java/org/apache/atlas/groovy/BinaryExpression.java
+51
-0
CastExpression.java
...src/main/java/org/apache/atlas/groovy/CastExpression.java
+44
-0
ClosureExpression.java
.../main/java/org/apache/atlas/groovy/ClosureExpression.java
+63
-0
CodeBlockExpression.java
...ain/java/org/apache/atlas/groovy/CodeBlockExpression.java
+61
-0
ComparisonExpression.java
...in/java/org/apache/atlas/groovy/ComparisonExpression.java
+64
-0
ComparisonOperatorExpression.java
...org/apache/atlas/groovy/ComparisonOperatorExpression.java
+32
-0
FieldExpression.java
...rc/main/java/org/apache/atlas/groovy/FieldExpression.java
+44
-0
FunctionCallExpression.java
.../java/org/apache/atlas/groovy/FunctionCallExpression.java
+86
-0
GroovyExpression.java
...c/main/java/org/apache/atlas/groovy/GroovyExpression.java
+34
-0
GroovyGenerationContext.java
...java/org/apache/atlas/groovy/GroovyGenerationContext.java
+68
-0
IdentifierExpression.java
...in/java/org/apache/atlas/groovy/IdentifierExpression.java
+42
-0
ListExpression.java
...src/main/java/org/apache/atlas/groovy/ListExpression.java
+60
-0
LiteralExpression.java
.../main/java/org/apache/atlas/groovy/LiteralExpression.java
+99
-0
LogicalExpression.java
.../main/java/org/apache/atlas/groovy/LogicalExpression.java
+46
-0
RangeExpression.java
...rc/main/java/org/apache/atlas/groovy/RangeExpression.java
+45
-0
TernaryOperatorExpression.java
...va/org/apache/atlas/groovy/TernaryOperatorExpression.java
+56
-0
TypeCoersionExpression.java
.../java/org/apache/atlas/groovy/TypeCoersionExpression.java
+44
-0
VariableAssignmentExpression.java
...org/apache/atlas/groovy/VariableAssignmentExpression.java
+58
-0
AtlasGraph.java
.../java/org/apache/atlas/repository/graphdb/AtlasGraph.java
+4
-3
Titan0Graph.java
...g/apache/atlas/repository/graphdb/titan0/Titan0Graph.java
+6
-5
release-log.txt
release-log.txt
+1
-0
DefaultGraphPersistenceStrategy.java
...tlas/discovery/graph/DefaultGraphPersistenceStrategy.java
+11
-36
Gremlin2ExpressionFactory.java
...a/org/apache/atlas/gremlin/Gremlin2ExpressionFactory.java
+223
-0
Gremlin3ExpressionFactory.java
...a/org/apache/atlas/gremlin/Gremlin3ExpressionFactory.java
+325
-0
GremlinExpressionFactory.java
...va/org/apache/atlas/gremlin/GremlinExpressionFactory.java
+410
-0
GraphPersistenceStrategies.scala
...a/org/apache/atlas/query/GraphPersistenceStrategies.scala
+23
-152
GremlinQuery.scala
.../src/main/scala/org/apache/atlas/query/GremlinQuery.scala
+246
-279
No files found.
common/src/main/java/org/apache/atlas/groovy/AbstractGroovyExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Abstract implementation of GroovyExpression that adds a convenient
* toString method.
*
*/
public
abstract
class
AbstractGroovyExpression
implements
GroovyExpression
{
@Override
public
String
toString
()
{
GroovyGenerationContext
ctx
=
new
GroovyGenerationContext
();
ctx
.
setParametersAllowed
(
false
);
generateGroovy
(
ctx
);
return
ctx
.
getQuery
();
}
}
common/src/main/java/org/apache/atlas/groovy/ArithmeticExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
import
org.apache.atlas.AtlasException
;
/**
* Represents an arithmetic expression such as a+b.
*/
public
class
ArithmeticExpression
extends
BinaryExpression
{
/**
* Allowed arithmetic operators.
*/
public
enum
ArithmeticOperator
{
PLUS
(
"+"
),
MINUS
(
"-"
),
TIMES
(
"*"
),
DIVIDE
(
"/"
),
MODULUS
(
"%"
);
private
String
groovyValue
;
ArithmeticOperator
(
String
groovyValue
)
{
this
.
groovyValue
=
groovyValue
;
}
public
String
getGroovyValue
()
{
return
groovyValue
;
}
public
static
ArithmeticOperator
lookup
(
String
groovyValue
)
throws
AtlasException
{
for
(
ArithmeticOperator
op
:
ArithmeticOperator
.
values
())
{
if
(
op
.
getGroovyValue
().
equals
(
groovyValue
))
{
return
op
;
}
}
throw
new
AtlasException
(
"Unknown Operator:"
+
groovyValue
);
}
}
public
ArithmeticExpression
(
GroovyExpression
left
,
ArithmeticOperator
op
,
GroovyExpression
right
)
{
super
(
left
,
op
.
getGroovyValue
(),
right
);
}
}
common/src/main/java/org/apache/atlas/groovy/BinaryExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Represents any kind of binary expression. This could
* be an arithmetic expression, such as a + 3, a boolean
* expression such as a < 5, or even a comparison function
* such as a <=> b.
*
*/
public
abstract
class
BinaryExpression
extends
AbstractGroovyExpression
{
private
GroovyExpression
left
;
private
GroovyExpression
right
;
private
String
op
;
public
BinaryExpression
(
GroovyExpression
left
,
String
op
,
GroovyExpression
right
)
{
this
.
left
=
left
;
this
.
op
=
op
;
this
.
right
=
right
;
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
left
.
generateGroovy
(
context
);
context
.
append
(
" "
);
context
.
append
(
op
);
context
.
append
(
" "
);
right
.
generateGroovy
(
context
);
}
}
common/src/main/java/org/apache/atlas/groovy/CastExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Groovy expression that represents a cast.
*/
public
class
CastExpression
extends
AbstractGroovyExpression
{
private
GroovyExpression
expr
;
private
String
className
;
public
CastExpression
(
GroovyExpression
expr
,
String
className
)
{
this
.
expr
=
expr
;
this
.
className
=
className
;
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
context
.
append
(
"(("
);
context
.
append
(
className
);
context
.
append
(
")"
);
expr
.
generateGroovy
(
context
);
context
.
append
(
")"
);
}
}
common/src/main/java/org/apache/atlas/groovy/ClosureExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.List
;
/**
* Groovy expression that represents a Groovy closure.
*/
public
class
ClosureExpression
extends
AbstractGroovyExpression
{
private
List
<
String
>
varNames
=
new
ArrayList
<>();
private
GroovyExpression
body
;
public
ClosureExpression
(
GroovyExpression
body
,
String
...
varNames
)
{
this
.
body
=
body
;
this
.
varNames
.
addAll
(
Arrays
.
asList
(
varNames
));
}
public
ClosureExpression
(
List
<
String
>
varNames
,
GroovyExpression
body
)
{
this
.
body
=
body
;
this
.
varNames
.
addAll
(
varNames
);
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
context
.
append
(
"{"
);
if
(!
varNames
.
isEmpty
())
{
Iterator
<
String
>
varIt
=
varNames
.
iterator
();
while
(
varIt
.
hasNext
())
{
String
varName
=
varIt
.
next
();
context
.
append
(
varName
);
if
(
varIt
.
hasNext
())
{
context
.
append
(
", "
);
}
}
context
.
append
(
"->"
);
}
body
.
generateGroovy
(
context
);
context
.
append
(
"}"
);
}
}
common/src/main/java/org/apache/atlas/groovy/CodeBlockExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.List
;
/**
* Groovy expression that represents a block of code
* that contains 0 or more statements that are delimited
* by semicolons.
*/
public
class
CodeBlockExpression
extends
AbstractGroovyExpression
{
private
List
<
GroovyExpression
>
body
=
new
ArrayList
<>();
public
void
addStatement
(
GroovyExpression
expr
)
{
body
.
add
(
expr
);
}
public
void
addStatements
(
List
<
GroovyExpression
>
exprs
)
{
body
.
addAll
(
exprs
);
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
/*
* the L:{} represents a groovy code block; the label is needed
* to distinguish it from a groovy closure.
*/
context
.
append
(
"L:{"
);
Iterator
<
GroovyExpression
>
stmtIt
=
body
.
iterator
();
while
(
stmtIt
.
hasNext
())
{
GroovyExpression
stmt
=
stmtIt
.
next
();
stmt
.
generateGroovy
(
context
);
if
(
stmtIt
.
hasNext
())
{
context
.
append
(
";"
);
}
}
context
.
append
(
"}"
);
}
}
common/src/main/java/org/apache/atlas/groovy/ComparisonExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
import
org.apache.atlas.AtlasException
;
/**
* Represents an expression that compares two expressions
* using a comparison operator (==, <, >, etc).
*
*/
public
class
ComparisonExpression
extends
BinaryExpression
{
/**
* Allowed comparison operators.
*
*/
public
enum
ComparisonOperator
{
GREATER_THAN_EQ_
(
">="
),
GREATER_THAN
(
">"
),
EQUALS
(
"=="
),
NOT_EQUALS
(
"!="
),
LESS_THAN
(
"<"
),
LESS_THAN_EQ
(
"<="
);
private
String
groovyValue
;
ComparisonOperator
(
String
groovyValue
)
{
this
.
groovyValue
=
groovyValue
;
}
public
String
getGroovyValue
()
{
return
groovyValue
;
}
public
static
ComparisonOperator
lookup
(
String
groovyValue
)
throws
AtlasException
{
for
(
ComparisonOperator
op
:
ComparisonOperator
.
values
())
{
if
(
op
.
getGroovyValue
().
equals
(
groovyValue
))
{
return
op
;
}
}
throw
new
AtlasException
(
"Unknown Operator:"
+
groovyValue
);
}
}
public
ComparisonExpression
(
GroovyExpression
left
,
ComparisonOperator
op
,
GroovyExpression
right
)
{
super
(
left
,
op
.
getGroovyValue
(),
right
);
}
}
common/src/main/java/org/apache/atlas/groovy/ComparisonOperatorExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Represents an expression that compares two expressions using
* the Groovy "spaceship" operator. This is basically the
* same as calling left.compareTo(right), except that it has
* built-in null handling and some other nice features.
*
*/
public
class
ComparisonOperatorExpression
extends
BinaryExpression
{
public
ComparisonOperatorExpression
(
GroovyExpression
left
,
GroovyExpression
right
)
{
super
(
left
,
"<=>"
,
right
);
}
}
common/src/main/java/org/apache/atlas/groovy/FieldExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Groovy expression that accesses a field in an object.
*/
public
class
FieldExpression
extends
AbstractGroovyExpression
{
private
GroovyExpression
target
;
private
String
fieldName
;
public
FieldExpression
(
GroovyExpression
target
,
String
fieldName
)
{
this
.
target
=
target
;
this
.
fieldName
=
fieldName
;
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
target
.
generateGroovy
(
context
);
context
.
append
(
".'"
);
context
.
append
(
fieldName
);
context
.
append
(
"'"
);
}
}
common/src/main/java/org/apache/atlas/groovy/FunctionCallExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.List
;
/**
* Groovy expression that calls a method on an object.
*/
public
class
FunctionCallExpression
extends
AbstractGroovyExpression
{
// null for global functions
private
GroovyExpression
target
;
private
String
functionName
;
private
List
<
GroovyExpression
>
arguments
=
new
ArrayList
<
GroovyExpression
>();
public
FunctionCallExpression
(
String
functionName
,
List
<?
extends
GroovyExpression
>
arguments
)
{
this
.
target
=
null
;
this
.
functionName
=
functionName
;
this
.
arguments
.
addAll
(
arguments
);
}
public
FunctionCallExpression
(
GroovyExpression
target
,
String
functionName
,
List
<?
extends
GroovyExpression
>
arguments
)
{
this
.
target
=
target
;
this
.
functionName
=
functionName
;
this
.
arguments
.
addAll
(
arguments
);
}
public
FunctionCallExpression
(
String
functionName
,
GroovyExpression
...
arguments
)
{
this
.
target
=
null
;
this
.
functionName
=
functionName
;
this
.
arguments
.
addAll
(
Arrays
.
asList
(
arguments
));
}
public
FunctionCallExpression
(
GroovyExpression
target
,
String
functionName
,
GroovyExpression
...
arguments
)
{
this
.
target
=
target
;
this
.
functionName
=
functionName
;
this
.
arguments
.
addAll
(
Arrays
.
asList
(
arguments
));
}
public
void
addArgument
(
GroovyExpression
expr
)
{
arguments
.
add
(
expr
);
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
if
(
target
!=
null
)
{
target
.
generateGroovy
(
context
);
context
.
append
(
"."
);
}
context
.
append
(
functionName
);
context
.
append
(
"("
);
Iterator
<
GroovyExpression
>
it
=
arguments
.
iterator
();
while
(
it
.
hasNext
())
{
GroovyExpression
expr
=
it
.
next
();
expr
.
generateGroovy
(
context
);
if
(
it
.
hasNext
())
{
context
.
append
(
", "
);
}
}
context
.
append
(
")"
);
}
}
common/src/main/java/org/apache/atlas/groovy/GroovyExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Represents an expression in the Groovy programming language, which
* is the language that Gremlin scripts are written and interpreted in.
*/
public
interface
GroovyExpression
{
/**
* Generates a groovy script from the expression.
*
* @param context
*/
void
generateGroovy
(
GroovyGenerationContext
context
);
}
common/src/main/java/org/apache/atlas/groovy/GroovyGenerationContext.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* Context used when generating Groovy queries. Keeps track of query parameters
* that are created during the process as well as the portion of the query that
* has been generated so far.
*
*/
public
class
GroovyGenerationContext
{
private
boolean
parametersAllowed
=
true
;
private
int
parameterCount
=
0
;
private
Map
<
String
,
Object
>
parameterValues
=
new
HashMap
<>();
//used to build up the groovy script
private
StringBuilder
generatedQuery
=
new
StringBuilder
();
public
void
setParametersAllowed
(
boolean
value
)
{
this
.
parametersAllowed
=
value
;
}
public
GroovyExpression
addParameter
(
Object
value
)
{
if
(
this
.
parametersAllowed
)
{
String
parameterName
=
"p"
+
(++
parameterCount
);
this
.
parameterValues
.
put
(
parameterName
,
value
);
return
new
IdentifierExpression
(
parameterName
);
}
else
{
LiteralExpression
expr
=
new
LiteralExpression
(
value
);
expr
.
setTranslateToParameter
(
false
);
return
expr
;
}
}
public
StringBuilder
append
(
String
gremlin
)
{
this
.
generatedQuery
.
append
(
gremlin
);
return
generatedQuery
;
}
public
String
getQuery
()
{
return
generatedQuery
.
toString
();
}
public
Map
<
String
,
Object
>
getParameters
()
{
return
Collections
.
unmodifiableMap
(
parameterValues
);
}
}
common/src/main/java/org/apache/atlas/groovy/IdentifierExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Groovy expression that references the variable with the given name.
*
*/
public
class
IdentifierExpression
extends
AbstractGroovyExpression
{
private
String
varName
;
public
IdentifierExpression
(
String
varName
)
{
this
.
varName
=
varName
;
}
public
String
getVariableName
()
{
return
varName
;
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
context
.
append
(
varName
);
}
}
common/src/main/java/org/apache/atlas/groovy/ListExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.List
;
/**
* Groovy expression that represents a list literal.
*/
public
class
ListExpression
extends
AbstractGroovyExpression
{
private
List
<
GroovyExpression
>
values
=
new
ArrayList
<>();
public
ListExpression
(
GroovyExpression
...
values
)
{
this
.
values
=
Arrays
.
asList
(
values
);
}
public
ListExpression
(
List
<?
extends
GroovyExpression
>
values
)
{
this
.
values
.
addAll
(
values
);
}
public
void
addArgument
(
GroovyExpression
expr
)
{
values
.
add
(
expr
);
}
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
context
.
append
(
"["
);
Iterator
<
GroovyExpression
>
it
=
values
.
iterator
();
while
(
it
.
hasNext
())
{
GroovyExpression
expr
=
it
.
next
();
expr
.
generateGroovy
(
context
);
if
(
it
.
hasNext
())
{
context
.
append
(
", "
);
}
}
context
.
append
(
"]"
);
}
}
common/src/main/java/org/apache/atlas/groovy/LiteralExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
/**
* Represents a literal value.
*/
public
class
LiteralExpression
implements
GroovyExpression
{
public
static
final
LiteralExpression
TRUE
=
new
LiteralExpression
(
true
);
public
static
final
LiteralExpression
FALSE
=
new
LiteralExpression
(
false
);
public
static
final
LiteralExpression
NULL
=
new
LiteralExpression
(
null
);
private
Object
value
;
private
boolean
translateToParameter
=
true
;
private
boolean
addTypeSuffix
=
false
;
public
LiteralExpression
(
Object
value
,
boolean
addTypeSuffix
)
{
this
.
value
=
value
;
this
.
translateToParameter
=
value
instanceof
String
;
this
.
addTypeSuffix
=
addTypeSuffix
;
}
public
LiteralExpression
(
Object
value
)
{
this
.
value
=
value
;
this
.
translateToParameter
=
value
instanceof
String
;
}
private
String
getTypeSuffix
()
{
if
(!
addTypeSuffix
)
{
return
""
;
}
if
(
value
.
getClass
()
==
Long
.
class
)
{
return
"L"
;
}
if
(
value
.
getClass
()
==
Float
.
class
)
{
return
"f"
;
}
if
(
value
.
getClass
()
==
Double
.
class
)
{
return
"d"
;
}
return
""
;
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
if
(
translateToParameter
)
{
GroovyExpression
result
=
context
.
addParameter
(
value
);
result
.
generateGroovy
(
context
);
return
;
}
if
(
value
instanceof
String
)
{
String
escapedValue
=
getEscapedValue
();
context
.
append
(
"'"
);
context
.
append
(
escapedValue
);
context
.
append
(
"'"
);
}
else
{
context
.
append
(
String
.
valueOf
(
value
));
context
.
append
(
getTypeSuffix
());
}
}
private
String
getEscapedValue
()
{
String
escapedValue
=
(
String
)
value
;
escapedValue
=
escapedValue
.
replaceAll
(
Pattern
.
quote
(
"\\"
),
Matcher
.
quoteReplacement
(
"\\\\"
));
escapedValue
=
escapedValue
.
replaceAll
(
Pattern
.
quote
(
"'"
),
Matcher
.
quoteReplacement
(
"\\'"
));
return
escapedValue
;
}
public
void
setTranslateToParameter
(
boolean
translateToParameter
)
{
this
.
translateToParameter
=
translateToParameter
;
}
}
common/src/main/java/org/apache/atlas/groovy/LogicalExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Represents a logical (and/or) expression.
*
*/
public
class
LogicalExpression
extends
BinaryExpression
{
/**
* Allowed logical operators.
*
*/
public
enum
LogicalOperator
{
AND
(
"&&"
),
OR
(
"||"
);
private
String
groovyValue
;
LogicalOperator
(
String
groovyValue
)
{
this
.
groovyValue
=
groovyValue
;
}
public
String
getGroovyValue
()
{
return
groovyValue
;
}
}
public
LogicalExpression
(
GroovyExpression
left
,
LogicalOperator
op
,
GroovyExpression
right
)
{
super
(
left
,
op
.
getGroovyValue
(),
right
);
}
}
common/src/main/java/org/apache/atlas/groovy/RangeExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Represents an "exclusive" range expression, e.g. [0..<10].
*/
public
class
RangeExpression
extends
AbstractGroovyExpression
{
private
GroovyExpression
parent
;
private
int
offset
;
private
int
count
;
public
RangeExpression
(
GroovyExpression
parent
,
int
offset
,
int
count
)
{
this
.
parent
=
parent
;
this
.
offset
=
offset
;
this
.
count
=
count
;
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
parent
.
generateGroovy
(
context
);
context
.
append
(
" ["
);
new
LiteralExpression
(
offset
).
generateGroovy
(
context
);
context
.
append
(
"..<"
);
new
LiteralExpression
(
count
).
generateGroovy
(
context
);
context
.
append
(
"]"
);
}
}
common/src/main/java/org/apache/atlas/groovy/TernaryOperatorExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Groovy expression that represents the ternary operator (expr ? trueValue :
* falseValue)
*/
public
class
TernaryOperatorExpression
extends
AbstractGroovyExpression
{
private
GroovyExpression
booleanExpr
;
private
GroovyExpression
trueValue
;
private
GroovyExpression
falseValue
;
public
TernaryOperatorExpression
(
GroovyExpression
booleanExpr
,
GroovyExpression
trueValue
,
GroovyExpression
falseValue
)
{
this
.
booleanExpr
=
booleanExpr
;
this
.
trueValue
=
trueValue
;
this
.
falseValue
=
falseValue
;
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
context
.
append
(
"(("
);
booleanExpr
.
generateGroovy
(
context
);
context
.
append
(
") ? ("
);
trueValue
.
generateGroovy
(
context
);
context
.
append
(
") : ("
);
falseValue
.
generateGroovy
(
context
);
context
.
append
(
"))"
);
}
public
String
toString
()
{
GroovyGenerationContext
context
=
new
GroovyGenerationContext
();
generateGroovy
(
context
);
return
context
.
getQuery
();
}
}
common/src/main/java/org/apache/atlas/groovy/TypeCoersionExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Groovy expression that represents a type coersion (e.g obj as Set).
*/
public
class
TypeCoersionExpression
extends
AbstractGroovyExpression
{
private
GroovyExpression
expr
;
private
String
className
;
public
TypeCoersionExpression
(
GroovyExpression
expr
,
String
className
)
{
this
.
expr
=
expr
;
this
.
className
=
className
;
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
context
.
append
(
"("
);
expr
.
generateGroovy
(
context
);
context
.
append
(
")"
);
context
.
append
(
" as "
);
context
.
append
(
className
);
}
}
common/src/main/java/org/apache/atlas/groovy/VariableAssignmentExpression.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
groovy
;
/**
* Groovy statement that assigns a value to a variable.
*/
public
class
VariableAssignmentExpression
extends
AbstractGroovyExpression
{
private
String
type
=
null
;
private
String
name
;
private
GroovyExpression
value
;
/**
* @param string
* @param v
*/
public
VariableAssignmentExpression
(
String
type
,
String
name
,
GroovyExpression
v
)
{
this
.
type
=
type
;
this
.
name
=
name
;
this
.
value
=
v
;
}
public
VariableAssignmentExpression
(
String
name
,
GroovyExpression
v
)
{
this
(
null
,
name
,
v
);
}
@Override
public
void
generateGroovy
(
GroovyGenerationContext
context
)
{
if
(
type
==
null
)
{
context
.
append
(
"def "
);
}
else
{
context
.
append
(
type
);
context
.
append
(
" "
);
}
context
.
append
(
name
);
context
.
append
(
" = "
);
value
.
generateGroovy
(
context
);
}
}
graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java
View file @
69af0ae7
...
...
@@ -23,6 +23,7 @@ import java.util.Set;
import
javax.script.ScriptException
;
import
org.apache.atlas.groovy.GroovyExpression
;
import
org.apache.atlas.typesystem.types.IDataType
;
/**
...
...
@@ -204,7 +205,7 @@ public interface AtlasGraph<V, E> {
* @param type
* @return
*/
String
generatePersisentToLogicalConversionExpression
(
String
valueExpr
,
IDataType
<?>
type
);
GroovyExpression
generatePersisentToLogicalConversionExpression
(
GroovyExpression
valueExpr
,
IDataType
<?>
type
);
/**
* Indicates whether or not stored values with the specified type need to be converted
...
...
@@ -240,7 +241,7 @@ public interface AtlasGraph<V, E> {
*
* @return
*/
String
getInitialIndexedPredicate
(
);
GroovyExpression
getInitialIndexedPredicate
(
GroovyExpression
parent
);
/**
* As an optimization, a graph database implementation may want to retrieve additional
...
...
@@ -249,7 +250,7 @@ public interface AtlasGraph<V, E> {
* avoid the need to make an extra REST API call to look up those edges. For implementations
* that do not require any kind of transform, an empty String should be returned.
*/
String
getOutputTransformationPredicate
(
boolean
isSelect
,
boolean
isPath
);
GroovyExpression
addOutputTransformationPredicate
(
GroovyExpression
expr
,
boolean
isSelect
,
boolean
isPath
);
/**
* Executes a Gremlin script, returns an object with the result.
...
...
graphdb/titan0/src/main/java/org/apache/atlas/repository/graphdb/titan0/Titan0Graph.java
View file @
69af0ae7
...
...
@@ -34,6 +34,7 @@ import javax.script.ScriptEngine;
import
javax.script.ScriptEngineManager
;
import
javax.script.ScriptException
;
import
org.apache.atlas.groovy.GroovyExpression
;
import
org.apache.atlas.repository.graphdb.AtlasEdge
;
import
org.apache.atlas.repository.graphdb.AtlasGraph
;
import
org.apache.atlas.repository.graphdb.AtlasGraphManagement
;
...
...
@@ -286,7 +287,7 @@ public class Titan0Graph implements AtlasGraph<Titan0Vertex, Titan0Edge> {
}
@Override
public
String
generatePersisentToLogicalConversionExpression
(
String
expr
,
IDataType
<?>
type
)
{
public
GroovyExpression
generatePersisentToLogicalConversionExpression
(
GroovyExpression
expr
,
IDataType
<?>
type
)
{
//nothing special needed, value is stored in required type
return
expr
;
...
...
@@ -304,13 +305,13 @@ public class Titan0Graph implements AtlasGraph<Titan0Vertex, Titan0Edge> {
}
@Override
public
String
getInitialIndexedPredicate
(
)
{
return
""
;
public
GroovyExpression
getInitialIndexedPredicate
(
GroovyExpression
expr
)
{
return
expr
;
}
@Override
public
String
getOutputTransformationPredicate
(
boolean
inSelect
,
boolean
isPath
)
{
return
""
;
public
GroovyExpression
addOutputTransformationPredicate
(
GroovyExpression
expr
,
boolean
inSelect
,
boolean
isPath
)
{
return
expr
;
}
public
Iterable
<
AtlasEdge
<
Titan0Vertex
,
Titan0Edge
>>
wrapEdges
(
Iterator
<
Edge
>
it
)
{
...
...
release-log.txt
View file @
69af0ae7
...
...
@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
ALL CHANGES:
ATLAS-1195 Clean up DSL Translation (jnhagelb via dkantor)
ATLAS-1139 Parameter name of a HDFS DataSet entity should contain filesystem path (svimal2106 via sumasai)
ATLAS-1200 Error Catalog enhancement (apoorvnaik via sumasai)
ATLAS-1207 Dataset exists query in lineage APIs takes longer (shwethags)
...
...
repository/src/main/java/org/apache/atlas/discovery/graph/DefaultGraphPersistenceStrategy.java
View file @
69af0ae7
...
...
@@ -23,16 +23,16 @@ import java.util.List;
import
javax.inject.Inject
;
import
org.apache.atlas.AtlasException
;
import
org.apache.atlas.
query.Expressions
;
import
org.apache.atlas.
groovy.GroovyExpression
;
import
org.apache.atlas.query.GraphPersistenceStrategies
;
import
org.apache.atlas.query.GraphPersistenceStrategies
$class
;
import
org.apache.atlas.query.IntSequence
;
import
org.apache.atlas.query.TypeUtils
;
import
org.apache.atlas.repository.Constants
;
import
org.apache.atlas.repository.MetadataRepository
;
import
org.apache.atlas.repository.RepositoryException
;
import
org.apache.atlas.repository.graph.GraphBackedMetadataRepository
;
import
org.apache.atlas.repository.graph.GraphHelper
;
import
org.apache.atlas.repository.graphdb.AtlasEdgeDirection
;
import
org.apache.atlas.repository.graphdb.AtlasGraph
;
import
org.apache.atlas.repository.graphdb.AtlasVertex
;
import
org.apache.atlas.repository.graphdb.GremlinVersion
;
...
...
@@ -105,11 +105,6 @@ public class DefaultGraphPersistenceStrategy implements GraphPersistenceStrategi
}
@Override
public
String
fieldPrefixInSelect
()
{
return
"it"
;
}
@Override
public
Id
getIdFromVertex
(
String
dataTypeName
,
AtlasVertex
vertex
)
{
return
GraphHelper
.
getIdFromVertex
(
dataTypeName
,
vertex
);
}
...
...
@@ -212,28 +207,13 @@ public class DefaultGraphPersistenceStrategy implements GraphPersistenceStrategi
}
@Override
public
String
gremlinCompOp
(
Expressions
.
ComparisonExpression
op
)
{
return
GraphPersistenceStrategies$class
.
gremlinCompOp
(
this
,
op
);
}
@Override
public
String
gremlinPrimitiveOp
(
Expressions
.
ComparisonExpression
op
)
{
return
GraphPersistenceStrategies$class
.
gremlinPrimitiveOp
(
this
,
op
);
}
@Override
public
String
loopObjectExpression
(
IDataType
<?>
dataType
)
{
return
GraphPersistenceStrategies$class
.
loopObjectExpression
(
this
,
dataType
);
public
AtlasEdgeDirection
instanceToTraitEdgeDirection
()
{
return
AtlasEdgeDirection
.
OUT
;
}
@Override
public
String
instanceToTraitEdgeDirection
()
{
return
"out"
;
}
@Override
public
String
traitToInstanceEdgeDirection
()
{
return
"in"
;
public
AtlasEdgeDirection
traitToInstanceEdgeDirection
()
{
return
AtlasEdgeDirection
.
IN
;
}
@Override
...
...
@@ -247,33 +227,28 @@ public class DefaultGraphPersistenceStrategy implements GraphPersistenceStrategi
}
@Override
public
scala
.
collection
.
Seq
<
String
>
typeTestExpression
(
String
typeName
,
IntSequence
intSeq
)
{
return
GraphPersistenceStrategies$class
.
typeTestExpression
(
this
,
typeName
,
intSeq
);
}
@Override
public
boolean
collectTypeInstancesIntoVar
()
{
return
GraphPersistenceStrategies$class
.
collectTypeInstancesIntoVar
(
this
);
}
@Override
public
boolean
addGraphVertexPrefix
(
scala
.
collection
.
Traversable
<
String
>
preStatements
)
{
public
boolean
addGraphVertexPrefix
(
scala
.
collection
.
Traversable
<
GroovyExpression
>
preStatements
)
{
return
GraphPersistenceStrategies$class
.
addGraphVertexPrefix
(
this
,
preStatements
);
}
@Override
public
GremlinVersion
getSupportedGremlinVersion
()
{
return
GraphPersistenceStrategies$class
.
getSupportedGremlinVersion
(
this
);
}
@Override
public
String
generatePersisentToLogicalConversionExpression
(
String
expr
,
IDataType
<?>
t
)
{
public
GroovyExpression
generatePersisentToLogicalConversionExpression
(
GroovyExpression
expr
,
IDataType
<?>
t
)
{
return
GraphPersistenceStrategies$class
.
generatePersisentToLogicalConversionExpression
(
this
,
expr
,
t
);
}
@Override
public
String
initialQueryCondition
(
)
{
return
GraphPersistenceStrategies$class
.
initialQueryCondition
(
this
);
public
GroovyExpression
addInitialQueryCondition
(
GroovyExpression
expr
)
{
return
GraphPersistenceStrategies$class
.
addInitialQueryCondition
(
this
,
expr
);
}
@Override
...
...
repository/src/main/java/org/apache/atlas/gremlin/Gremlin2ExpressionFactory.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
gremlin
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.apache.atlas.AtlasException
;
import
org.apache.atlas.groovy.ClosureExpression
;
import
org.apache.atlas.groovy.ComparisonExpression
;
import
org.apache.atlas.groovy.ComparisonOperatorExpression
;
import
org.apache.atlas.groovy.FieldExpression
;
import
org.apache.atlas.groovy.FunctionCallExpression
;
import
org.apache.atlas.groovy.GroovyExpression
;
import
org.apache.atlas.groovy.IdentifierExpression
;
import
org.apache.atlas.groovy.ListExpression
;
import
org.apache.atlas.groovy.LiteralExpression
;
import
org.apache.atlas.groovy.LogicalExpression
;
import
org.apache.atlas.groovy.RangeExpression
;
import
org.apache.atlas.groovy.TernaryOperatorExpression
;
import
org.apache.atlas.groovy.ComparisonExpression.ComparisonOperator
;
import
org.apache.atlas.groovy.LogicalExpression.LogicalOperator
;
import
org.apache.atlas.query.GraphPersistenceStrategies
;
import
org.apache.atlas.query.TypeUtils.FieldInfo
;
import
org.apache.atlas.typesystem.types.IDataType
;
/**
* Generates gremlin query expressions using Gremlin 2 syntax.
*
*/
public
class
Gremlin2ExpressionFactory
extends
GremlinExpressionFactory
{
private
static
final
String
LOOP_METHOD
=
"loop"
;
private
static
final
String
CONTAINS
=
"contains"
;
private
static
final
String
LOOP_COUNT_FIELD
=
"loops"
;
private
static
final
String
PATH_FIELD
=
"path"
;
private
static
final
String
ENABLE_PATH_METHOD
=
"enablePath"
;
private
static
final
String
BACK_METHOD
=
"back"
;
@Override
public
GroovyExpression
generateLogicalExpression
(
GroovyExpression
parent
,
String
operator
,
List
<
GroovyExpression
>
operands
)
{
return
new
FunctionCallExpression
(
parent
,
operator
,
operands
);
}
@Override
public
GroovyExpression
generateBackReferenceExpression
(
GroovyExpression
parent
,
boolean
inSelect
,
String
alias
)
{
if
(
inSelect
)
{
return
getFieldInSelect
();
}
else
{
return
new
FunctionCallExpression
(
parent
,
BACK_METHOD
,
new
LiteralExpression
(
alias
));
}
}
@Override
public
GroovyExpression
getLoopExpressionParent
(
GroovyExpression
inputQry
)
{
return
inputQry
;
}
@Override
public
GroovyExpression
generateLoopExpression
(
GroovyExpression
parent
,
GraphPersistenceStrategies
s
,
IDataType
dataType
,
GroovyExpression
loopExpr
,
String
alias
,
Integer
times
)
{
GroovyExpression
emitExpr
=
generateLoopEmitExpression
(
s
,
dataType
);
//note that in Gremlin 2 (unlike Gremlin 3), the parent is not explicitly used. It is incorporated
//in the loopExpr.
GroovyExpression
whileFunction
=
null
;
if
(
times
!=
null
)
{
GroovyExpression
loopsExpr
=
new
FieldExpression
(
getItVariable
(),
LOOP_COUNT_FIELD
);
GroovyExpression
timesExpr
=
new
LiteralExpression
(
times
);
whileFunction
=
new
ClosureExpression
(
new
ComparisonExpression
(
loopsExpr
,
ComparisonOperator
.
LESS_THAN
,
timesExpr
));
}
else
{
GroovyExpression
pathExpr
=
new
FieldExpression
(
getItVariable
(),
PATH_FIELD
);
GroovyExpression
itObjectExpr
=
getCurrentObjectExpression
();
GroovyExpression
pathContainsExpr
=
new
FunctionCallExpression
(
pathExpr
,
CONTAINS
,
itObjectExpr
);
whileFunction
=
new
ClosureExpression
(
new
TernaryOperatorExpression
(
pathContainsExpr
,
LiteralExpression
.
FALSE
,
LiteralExpression
.
TRUE
));
}
GroovyExpression
emitFunction
=
new
ClosureExpression
(
emitExpr
);
GroovyExpression
loopCall
=
new
FunctionCallExpression
(
loopExpr
,
LOOP_METHOD
,
new
LiteralExpression
(
alias
),
whileFunction
,
emitFunction
);
return
new
FunctionCallExpression
(
loopCall
,
ENABLE_PATH_METHOD
);
}
@Override
public
GroovyExpression
typeTestExpression
(
GraphPersistenceStrategies
s
,
String
typeName
,
GroovyExpression
itRef
)
{
GroovyExpression
typeAttrExpr
=
new
FieldExpression
(
itRef
,
s
.
typeAttributeName
());
GroovyExpression
superTypeAttrExpr
=
new
FieldExpression
(
itRef
,
s
.
superTypeAttributeName
());
GroovyExpression
typeNameExpr
=
new
LiteralExpression
(
typeName
);
GroovyExpression
typeMatchesExpr
=
new
ComparisonExpression
(
typeAttrExpr
,
ComparisonOperator
.
EQUALS
,
typeNameExpr
);
GroovyExpression
isSuperTypeExpr
=
new
FunctionCallExpression
(
superTypeAttrExpr
,
CONTAINS
,
typeNameExpr
);
GroovyExpression
hasSuperTypeAttrExpr
=
superTypeAttrExpr
;
GroovyExpression
superTypeMatchesExpr
=
new
TernaryOperatorExpression
(
hasSuperTypeAttrExpr
,
isSuperTypeExpr
,
LiteralExpression
.
FALSE
);
return
new
LogicalExpression
(
typeMatchesExpr
,
LogicalOperator
.
OR
,
superTypeMatchesExpr
);
}
@Override
public
GroovyExpression
generateSelectExpression
(
GroovyExpression
parent
,
List
<
LiteralExpression
>
sourceNames
,
List
<
GroovyExpression
>
srcExprs
)
{
GroovyExpression
srcNamesExpr
=
new
ListExpression
(
sourceNames
);
List
<
GroovyExpression
>
selectArgs
=
new
ArrayList
<>();
selectArgs
.
add
(
srcNamesExpr
);
for
(
GroovyExpression
expr
:
srcExprs
)
{
selectArgs
.
add
(
new
ClosureExpression
(
expr
));
}
return
new
FunctionCallExpression
(
parent
,
SELECT_METHOD
,
selectArgs
);
}
@Override
public
GroovyExpression
generateFieldExpression
(
GroovyExpression
parent
,
FieldInfo
fInfo
,
String
propertyName
,
boolean
inSelect
)
{
return
new
FieldExpression
(
parent
,
propertyName
);
}
@Override
public
GroovyExpression
generateHasExpression
(
GraphPersistenceStrategies
s
,
GroovyExpression
parent
,
String
propertyName
,
String
symbol
,
GroovyExpression
requiredValue
,
FieldInfo
fInfo
)
throws
AtlasException
{
GroovyExpression
op
=
gremlin2CompOp
(
symbol
);
GroovyExpression
propertyNameExpr
=
new
LiteralExpression
(
propertyName
);
return
new
FunctionCallExpression
(
parent
,
HAS_METHOD
,
propertyNameExpr
,
op
,
requiredValue
);
}
private
GroovyExpression
gremlin2CompOp
(
String
op
)
throws
AtlasException
{
GroovyExpression
tExpr
=
new
IdentifierExpression
(
"T"
);
if
(
op
.
equals
(
"="
))
{
return
new
FieldExpression
(
tExpr
,
"eq"
);
}
if
(
op
.
equals
(
"!="
))
{
return
new
FieldExpression
(
tExpr
,
"neq"
);
}
if
(
op
.
equals
(
">"
))
{
return
new
FieldExpression
(
tExpr
,
"gt"
);
}
if
(
op
.
equals
(
">="
))
{
return
new
FieldExpression
(
tExpr
,
"gte"
);
}
if
(
op
.
equals
(
"<"
))
{
return
new
FieldExpression
(
tExpr
,
"lt"
);
}
if
(
op
.
equals
(
"<="
))
{
return
new
FieldExpression
(
tExpr
,
"lte"
);
}
throw
new
AtlasException
(
"Comparison operator "
+
op
+
" not supported in Gremlin"
);
}
@Override
protected
GroovyExpression
initialExpression
(
GraphPersistenceStrategies
s
,
GroovyExpression
varExpr
)
{
return
new
FunctionCallExpression
(
varExpr
,
"_"
);
}
@Override
public
GroovyExpression
generateLimitExpression
(
GroovyExpression
parent
,
int
offset
,
int
totalRows
)
{
return
new
RangeExpression
(
parent
,
offset
,
totalRows
);
}
@Override
public
List
<
GroovyExpression
>
getOrderFieldParents
()
{
GroovyExpression
itExpr
=
getItVariable
();
List
<
GroovyExpression
>
result
=
new
ArrayList
<>(
2
);
result
.
add
(
new
FieldExpression
(
itExpr
,
"a"
));
result
.
add
(
new
FieldExpression
(
itExpr
,
"b"
));
return
result
;
}
@Override
public
GroovyExpression
generateOrderByExpression
(
GroovyExpression
parent
,
List
<
GroovyExpression
>
translatedOrderBy
,
boolean
isAscending
)
{
GroovyExpression
itExpr
=
getItVariable
();
GroovyExpression
aPropertyExpr
=
translatedOrderBy
.
get
(
0
);
GroovyExpression
bPropertyExpr
=
translatedOrderBy
.
get
(
1
);
GroovyExpression
aPropertyNotNull
=
new
ComparisonExpression
(
aPropertyExpr
,
ComparisonOperator
.
NOT_EQUALS
,
LiteralExpression
.
NULL
);
GroovyExpression
bPropertyNotNull
=
new
ComparisonExpression
(
bPropertyExpr
,
ComparisonOperator
.
NOT_EQUALS
,
LiteralExpression
.
NULL
);
GroovyExpression
aCondition
=
new
TernaryOperatorExpression
(
aPropertyNotNull
,
new
FunctionCallExpression
(
aPropertyExpr
,
TO_LOWER_CASE_METHOD
),
aPropertyExpr
);
GroovyExpression
bCondition
=
new
TernaryOperatorExpression
(
bPropertyNotNull
,
new
FunctionCallExpression
(
bPropertyExpr
,
TO_LOWER_CASE_METHOD
),
bPropertyExpr
);
GroovyExpression
comparisonFunction
=
null
;
if
(
isAscending
)
{
comparisonFunction
=
new
ComparisonOperatorExpression
(
aCondition
,
bCondition
);
}
else
{
comparisonFunction
=
new
ComparisonOperatorExpression
(
bCondition
,
aCondition
);
}
return
new
FunctionCallExpression
(
parent
,
ORDER_METHOD
,
new
ClosureExpression
(
comparisonFunction
));
}
@Override
public
GroovyExpression
getAnonymousTraversalExpression
()
{
return
new
FunctionCallExpression
(
"_"
);
}
@Override
public
GroovyExpression
getFieldInSelect
()
{
return
getItVariable
();
}
}
repository/src/main/java/org/apache/atlas/gremlin/Gremlin3ExpressionFactory.java
0 → 100644
View file @
69af0ae7
/**
* 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
.
atlas
.
gremlin
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.apache.atlas.AtlasException
;
import
org.apache.atlas.groovy.CastExpression
;
import
org.apache.atlas.groovy.ClosureExpression
;
import
org.apache.atlas.groovy.ComparisonExpression
;
import
org.apache.atlas.groovy.ComparisonOperatorExpression
;
import
org.apache.atlas.groovy.FunctionCallExpression
;
import
org.apache.atlas.groovy.GroovyExpression
;
import
org.apache.atlas.groovy.IdentifierExpression
;
import
org.apache.atlas.groovy.LiteralExpression
;
import
org.apache.atlas.groovy.LogicalExpression
;
import
org.apache.atlas.groovy.TypeCoersionExpression
;
import
org.apache.atlas.groovy.ComparisonExpression.ComparisonOperator
;
import
org.apache.atlas.groovy.LogicalExpression.LogicalOperator
;
import
org.apache.atlas.query.GraphPersistenceStrategies
;
import
org.apache.atlas.query.TypeUtils.FieldInfo
;
import
org.apache.atlas.repository.graph.AtlasGraphProvider
;
import
org.apache.atlas.repository.graphdb.AtlasGraph
;
import
org.apache.atlas.typesystem.types.AttributeInfo
;
import
org.apache.atlas.typesystem.types.IDataType
;
/**
* Generates gremlin query expressions using Gremlin 3 syntax.
*
*/
public
class
Gremlin3ExpressionFactory
extends
GremlinExpressionFactory
{
private
static
final
String
VERTEX_LIST_CLASS
=
"List<Vertex>"
;
private
static
final
String
VERTEX_ARRAY_CLASS
=
"Vertex[]"
;
private
static
final
String
OBJECT_ARRAY_CLASS
=
"Object[]"
;
private
static
final
String
VERTEX_CLASS
=
"Vertex"
;
private
static
final
String
FUNCTION_CLASS
=
"Function"
;
private
static
final
String
VALUE_METHOD
=
"value"
;
private
static
final
String
IS_PRESENT_METHOD
=
"isPresent"
;
private
static
final
String
MAP_METHOD
=
"map"
;
private
static
final
String
VALUES_METHOD
=
"values"
;
private
static
final
String
GET_METHOD
=
"get"
;
private
static
final
String
OR_ELSE_METHOD
=
"orElse"
;
private
static
final
String
PROPERTY_METHOD
=
"property"
;
private
static
final
String
BY_METHOD
=
"by"
;
private
static
final
String
EQ_METHOD
=
"eq"
;
private
static
final
String
EMIT_METHOD
=
"emit"
;
private
static
final
String
TIMES_METHOD
=
"times"
;
private
static
final
String
REPEAT_METHOD
=
"repeat"
;
private
static
final
String
RANGE_METHOD
=
"range"
;
private
static
final
String
LAST_METHOD
=
"last"
;
private
static
final
String
WHERE_METHOD
=
"where"
;
private
static
final
String
TO_STRING_METHOD
=
"toString"
;
@Override
public
GroovyExpression
generateLogicalExpression
(
GroovyExpression
parent
,
String
operator
,
List
<
GroovyExpression
>
operands
)
{
if
(
operands
.
size
()
==
1
)
{
// gremlin 3 treats one element expressions as 'false'. Avoid
// creating a boolean expression in this case. Inline the expression
// note: we can't simply omit it, since it will cause us to traverse
// the edge!
// use 'where' instead
GroovyExpression
expr
=
operands
.
get
(
0
);
// if child is a back expression, that expression becomes an
// argument to where
return
new
FunctionCallExpression
(
parent
,
WHERE_METHOD
,
expr
);
}
else
{
// Gremlin 3 does not support _() syntax
//
return
new
FunctionCallExpression
(
parent
,
operator
,
operands
);
}
}
@Override
public
GroovyExpression
generateBackReferenceExpression
(
GroovyExpression
parent
,
boolean
inSelect
,
String
alias
)
{
if
(
inSelect
)
{
return
getFieldInSelect
();
}
else
{
return
new
FunctionCallExpression
(
parent
,
SELECT_METHOD
,
new
LiteralExpression
(
alias
));
}
}
@Override
public
GroovyExpression
typeTestExpression
(
GraphPersistenceStrategies
s
,
String
typeName
,
GroovyExpression
itRef
)
{
LiteralExpression
typeAttrExpr
=
new
LiteralExpression
(
s
.
typeAttributeName
());
LiteralExpression
superTypeAttrExpr
=
new
LiteralExpression
(
s
.
superTypeAttributeName
());
LiteralExpression
typeNameExpr
=
new
LiteralExpression
(
typeName
);
FunctionCallExpression
result
=
new
FunctionCallExpression
(
HAS_METHOD
,
typeAttrExpr
,
new
FunctionCallExpression
(
EQ_METHOD
,
typeNameExpr
));
result
=
new
FunctionCallExpression
(
result
,
"or"
);
result
=
new
FunctionCallExpression
(
HAS_METHOD
,
superTypeAttrExpr
,
new
FunctionCallExpression
(
EQ_METHOD
,
typeNameExpr
));
return
result
;
}
@Override
public
GroovyExpression
generateLoopExpression
(
GroovyExpression
parent
,
GraphPersistenceStrategies
s
,
IDataType
dataType
,
GroovyExpression
loopExpr
,
String
alias
,
Integer
times
)
{
GroovyExpression
emitExpr
=
generateLoopEmitExpression
(
s
,
dataType
);
GroovyExpression
result
=
new
FunctionCallExpression
(
parent
,
REPEAT_METHOD
,
loopExpr
);
if
(
times
!=
null
)
{
GroovyExpression
timesExpr
=
new
LiteralExpression
(
times
);
result
=
new
FunctionCallExpression
(
result
,
TIMES_METHOD
,
timesExpr
);
}
result
=
new
FunctionCallExpression
(
result
,
EMIT_METHOD
,
emitExpr
);
return
result
;
}
@Override
public
GroovyExpression
getLoopExpressionParent
(
GroovyExpression
inputQry
)
{
GroovyExpression
curTraversal
=
new
IdentifierExpression
(
"__"
);
return
curTraversal
;
}
@Override
public
GroovyExpression
generateSelectExpression
(
GroovyExpression
parent
,
List
<
LiteralExpression
>
sourceNames
,
List
<
GroovyExpression
>
srcExprs
)
{
FunctionCallExpression
result
=
new
FunctionCallExpression
(
parent
,
SELECT_METHOD
,
sourceNames
);
for
(
GroovyExpression
expr
:
srcExprs
)
{
GroovyExpression
closure
=
new
ClosureExpression
(
expr
);
GroovyExpression
castClosure
=
new
TypeCoersionExpression
(
closure
,
FUNCTION_CLASS
);
result
=
new
FunctionCallExpression
(
result
,
BY_METHOD
,
castClosure
);
}
return
result
;
}
@Override
public
GroovyExpression
generateFieldExpression
(
GroovyExpression
parent
,
FieldInfo
fInfo
,
String
propertyName
,
boolean
inSelect
)
{
AttributeInfo
attrInfo
=
fInfo
.
attrInfo
();
IDataType
attrType
=
attrInfo
.
dataType
();
GroovyExpression
propertyNameExpr
=
new
LiteralExpression
(
propertyName
);
AtlasGraph
graph
=
AtlasGraphProvider
.
getGraphInstance
();
if
(
inSelect
)
{
GroovyExpression
expr
=
new
FunctionCallExpression
(
parent
,
PROPERTY_METHOD
,
propertyNameExpr
);
expr
=
new
FunctionCallExpression
(
expr
,
OR_ELSE_METHOD
,
LiteralExpression
.
NULL
);
return
graph
.
generatePersisentToLogicalConversionExpression
(
expr
,
attrType
);
}
else
{
GroovyExpression
unmapped
=
new
FunctionCallExpression
(
parent
,
VALUES_METHOD
,
propertyNameExpr
);
if
(
graph
.
isPropertyValueConversionNeeded
(
attrType
))
{
GroovyExpression
toConvert
=
new
FunctionCallExpression
(
getItVariable
(),
GET_METHOD
);
GroovyExpression
conversionFunction
=
graph
.
generatePersisentToLogicalConversionExpression
(
toConvert
,
attrType
);
return
new
FunctionCallExpression
(
unmapped
,
MAP_METHOD
,
new
ClosureExpression
(
conversionFunction
));
}
else
{
return
unmapped
;
}
}
}
private
ComparisonOperator
getGroovyOperator
(
String
symbol
)
throws
AtlasException
{
String
toFind
=
symbol
;
if
(
toFind
.
equals
(
"="
))
{
toFind
=
"=="
;
}
return
ComparisonOperator
.
lookup
(
toFind
);
}
private
String
getComparisonFunction
(
String
op
)
throws
AtlasException
{
if
(
op
.
equals
(
"="
))
{
return
"eq"
;
}
if
(
op
.
equals
(
"!="
))
{
return
"neq"
;
}
if
(
op
.
equals
(
">"
))
{
return
"gt"
;
}
if
(
op
.
equals
(
">="
))
{
return
"gte"
;
}
if
(
op
.
equals
(
"<"
))
{
return
"lt"
;
}
if
(
op
.
equals
(
"<="
))
{
return
"lte"
;
}
throw
new
AtlasException
(
"Comparison operator "
+
op
+
" not supported in Gremlin"
);
}
@Override
public
GroovyExpression
generateHasExpression
(
GraphPersistenceStrategies
s
,
GroovyExpression
parent
,
String
propertyName
,
String
symbol
,
GroovyExpression
requiredValue
,
FieldInfo
fInfo
)
throws
AtlasException
{
AttributeInfo
attrInfo
=
fInfo
.
attrInfo
();
IDataType
attrType
=
attrInfo
.
dataType
();
GroovyExpression
propertNameExpr
=
new
LiteralExpression
(
propertyName
);
if
(
s
.
isPropertyValueConversionNeeded
(
attrType
))
{
// for some types, the logical value cannot be stored directly in
// the underlying graph,
// and conversion logic is needed to convert the persistent form of
// the value
// to the actual value. In cases like this, we generate a conversion
// expression to
// do this conversion and use the filter step to perform the
// comparsion in the gremlin query
GroovyExpression
itExpr
=
getItVariable
();
GroovyExpression
vertexExpr
=
new
CastExpression
(
new
FunctionCallExpression
(
itExpr
,
GET_METHOD
),
VERTEX_CLASS
);
GroovyExpression
propertyValueExpr
=
new
FunctionCallExpression
(
vertexExpr
,
VALUE_METHOD
,
propertNameExpr
);
GroovyExpression
conversionExpr
=
s
.
generatePersisentToLogicalConversionExpression
(
propertyValueExpr
,
attrType
);
GroovyExpression
propertyIsPresentExpression
=
new
FunctionCallExpression
(
new
FunctionCallExpression
(
vertexExpr
,
PROPERTY_METHOD
,
propertNameExpr
),
IS_PRESENT_METHOD
);
GroovyExpression
valueMatchesExpr
=
new
ComparisonExpression
(
conversionExpr
,
getGroovyOperator
(
symbol
),
requiredValue
);
GroovyExpression
filterCondition
=
new
LogicalExpression
(
propertyIsPresentExpression
,
LogicalOperator
.
AND
,
valueMatchesExpr
);
GroovyExpression
filterFunction
=
new
ClosureExpression
(
filterCondition
);
return
new
FunctionCallExpression
(
parent
,
FILTER_METHOD
,
filterFunction
);
}
else
{
GroovyExpression
valueMatches
=
new
FunctionCallExpression
(
getComparisonFunction
(
symbol
),
requiredValue
);
return
new
FunctionCallExpression
(
parent
,
HAS_METHOD
,
propertNameExpr
,
valueMatches
);
}
}
@Override
protected
GroovyExpression
initialExpression
(
GraphPersistenceStrategies
s
,
GroovyExpression
varExpr
)
{
// this bit of groovy magic converts the set of vertices in varName into
// a String containing the ids of all the vertices. This becomes the
// argument
// to g.V(). This is needed because Gremlin 3 does not support
// _()
// s"g.V(${varName}.collect{it.id()} as String[])"
GroovyExpression
gExpr
=
getGraph
();
GroovyExpression
varRefExpr
=
new
TypeCoersionExpression
(
varExpr
,
OBJECT_ARRAY_CLASS
);
FunctionCallExpression
expr
=
new
FunctionCallExpression
(
gExpr
,
V_METHOD
,
varRefExpr
);
return
s
.
addInitialQueryCondition
(
expr
);
}
@Override
public
GroovyExpression
generateLimitExpression
(
GroovyExpression
parent
,
int
offset
,
int
totalRows
)
{
return
new
FunctionCallExpression
(
parent
,
RANGE_METHOD
,
new
LiteralExpression
(
offset
),
new
LiteralExpression
(
totalRows
));
}
@Override
public
List
<
GroovyExpression
>
getOrderFieldParents
()
{
List
<
GroovyExpression
>
result
=
new
ArrayList
<>(
1
);
result
.
add
(
null
);
return
result
;
}
@Override
public
GroovyExpression
generateOrderByExpression
(
GroovyExpression
parent
,
List
<
GroovyExpression
>
translatedOrderBy
,
boolean
isAscending
)
{
GroovyExpression
orderByClause
=
translatedOrderBy
.
get
(
0
);
GroovyExpression
aExpr
=
new
IdentifierExpression
(
"a"
);
GroovyExpression
bExpr
=
new
IdentifierExpression
(
"b"
);
GroovyExpression
aCompExpr
=
new
FunctionCallExpression
(
new
FunctionCallExpression
(
aExpr
,
TO_STRING_METHOD
),
TO_LOWER_CASE_METHOD
);
GroovyExpression
bCompExpr
=
new
FunctionCallExpression
(
new
FunctionCallExpression
(
bExpr
,
TO_STRING_METHOD
),
TO_LOWER_CASE_METHOD
);
GroovyExpression
comparisonExpr
=
null
;
if
(
isAscending
)
{
comparisonExpr
=
new
ComparisonOperatorExpression
(
aCompExpr
,
bCompExpr
);
}
else
{
comparisonExpr
=
new
ComparisonOperatorExpression
(
bCompExpr
,
aCompExpr
);
}
ClosureExpression
comparisonFunction
=
new
ClosureExpression
(
comparisonExpr
,
"a"
,
"b"
);
return
new
FunctionCallExpression
(
new
FunctionCallExpression
(
parent
,
ORDER_METHOD
),
BY_METHOD
,
orderByClause
,
comparisonFunction
);
}
@Override
public
GroovyExpression
getAnonymousTraversalExpression
()
{
return
null
;
}
@Override
public
GroovyExpression
getFieldInSelect
()
{
// this logic is needed to remove extra results from
// what is emitted by repeat loops. Technically
// for queries that don't have a loop in them we could just use "it"
// the reason for this is that in repeat loops with an alias,
// although the alias gets set to the right value, for some
// reason the select actually includes all vertices that were traversed
// through in the loop. In these cases, we only want the last vertex
// traversed in the loop to be selected. The logic here handles that
// case by converting the result to a list and just selecting the
// last item from it.
GroovyExpression
itExpr
=
getItVariable
();
GroovyExpression
expr1
=
new
TypeCoersionExpression
(
itExpr
,
VERTEX_ARRAY_CLASS
);
GroovyExpression
expr2
=
new
TypeCoersionExpression
(
expr1
,
VERTEX_LIST_CLASS
);
return
new
FunctionCallExpression
(
expr2
,
LAST_METHOD
);
}
}
repository/src/main/java/org/apache/atlas/gremlin/GremlinExpressionFactory.java
0 → 100644
View file @
69af0ae7
/**
* 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_METHOD 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
.
atlas
.
gremlin
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
org.apache.atlas.AtlasException
;
import
org.apache.atlas.groovy.ArithmeticExpression
;
import
org.apache.atlas.groovy.ClosureExpression
;
import
org.apache.atlas.groovy.FieldExpression
;
import
org.apache.atlas.groovy.FunctionCallExpression
;
import
org.apache.atlas.groovy.GroovyExpression
;
import
org.apache.atlas.groovy.IdentifierExpression
;
import
org.apache.atlas.groovy.ListExpression
;
import
org.apache.atlas.groovy.LiteralExpression
;
import
org.apache.atlas.groovy.TypeCoersionExpression
;
import
org.apache.atlas.groovy.VariableAssignmentExpression
;
import
org.apache.atlas.groovy.ArithmeticExpression.ArithmeticOperator
;
import
org.apache.atlas.query.GraphPersistenceStrategies
;
import
org.apache.atlas.query.IntSequence
;
import
org.apache.atlas.query.TypeUtils.FieldInfo
;
import
org.apache.atlas.repository.graph.AtlasGraphProvider
;
import
org.apache.atlas.repository.graphdb.AtlasEdgeDirection
;
import
org.apache.atlas.repository.graphdb.GremlinVersion
;
import
org.apache.atlas.typesystem.types.IDataType
;
/**
* Factory to generate Groovy expressions representing Gremlin syntax that that
* are independent of the specific version of Gremlin that is being used.
*
*/
public
abstract
class
GremlinExpressionFactory
{
private
static
final
String
G_VARIABLE
=
"g"
;
private
static
final
String
IT_VARIABLE
=
"it"
;
private
static
final
String
SET_CLASS
=
"Set"
;
private
static
final
String
OBJECT_FIELD
=
"object"
;
protected
static
final
String
V_METHOD
=
"V"
;
protected
static
final
String
FILTER_METHOD
=
"filter"
;
private
static
final
String
PATH_METHOD
=
"path"
;
private
static
final
String
AS_METHOD
=
"as"
;
private
static
final
String
FILL_METHOD
=
"fill"
;
protected
static
final
String
HAS_METHOD
=
"has"
;
protected
static
final
String
TO_LOWER_CASE_METHOD
=
"toLowerCase"
;
protected
static
final
String
SELECT_METHOD
=
"select"
;
protected
static
final
String
ORDER_METHOD
=
"order"
;
public
static
final
GremlinExpressionFactory
INSTANCE
=
AtlasGraphProvider
.
getGraphInstance
()
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
THREE
?
new
Gremlin3ExpressionFactory
()
:
new
Gremlin2ExpressionFactory
();
/**
* Gets the expression to use as the parent when translating the loop
* expression in a loop
*
* @param inputQry
* the
* @return
*/
public
abstract
GroovyExpression
getLoopExpressionParent
(
GroovyExpression
inputQry
);
/**
* Generates a loop expression.
*
* @param parent
* the parent of the loop expression
* @param emitExpr
* Expression with the value that should be emitted by the loop
* expression.
* @param loopExpr
* the query expression that is being executed repeatedly
* executed in a loop
* @param alias
* The alias of the expression being looped over
* @param times
* the number of times to repeat, or null if a times condition
* should not be used.
* @return
*/
public
abstract
GroovyExpression
generateLoopExpression
(
GroovyExpression
parent
,
GraphPersistenceStrategies
s
,
IDataType
dataType
,
GroovyExpression
loopExpr
,
String
alias
,
Integer
times
);
/**
* Generates a logical (and/or) expression with the given operands.
* @param parent
* @param operator
* @param operands
* @return
*/
public
abstract
GroovyExpression
generateLogicalExpression
(
GroovyExpression
parent
,
String
operator
,
List
<
GroovyExpression
>
operands
);
/**
* Generates a back reference expression that refers to the given alias.
*
* @param parent
* @param inSelect
* @param alias
* @return
*/
public
abstract
GroovyExpression
generateBackReferenceExpression
(
GroovyExpression
parent
,
boolean
inSelect
,
String
alias
);
/**
* Generates a select expression
*
* @param parent
* @param sourceNames
* the names of the select fields
* @param srcExprs
* the corresponding values to return
* @return
*/
public
abstract
GroovyExpression
generateSelectExpression
(
GroovyExpression
parent
,
List
<
LiteralExpression
>
sourceNames
,
List
<
GroovyExpression
>
srcExprs
);
/**
* Generates a an expression that gets the value of the given property from the
* vertex presented by the parent.
*
* @param parent
* @param fInfo
* @param propertyName
* @param inSelect
* @return
*/
public
abstract
GroovyExpression
generateFieldExpression
(
GroovyExpression
parent
,
FieldInfo
fInfo
,
String
propertyName
,
boolean
inSelect
);
/**
* Generates a has expression that checks whether the vertices match a specific condition
*
* @param s
* @param parent the object that we should call apply the "has" condition to.
* @param propertyName the name of the property whose value we are comparing
* @param symbol comparsion operator symbol ('=','<', etc.)
* @param requiredValue the value to compare against
* @param fInfo info about the field whose value we are checking
* @return
* @throws AtlasException
*/
public
abstract
GroovyExpression
generateHasExpression
(
GraphPersistenceStrategies
s
,
GroovyExpression
parent
,
String
propertyName
,
String
symbol
,
GroovyExpression
requiredValue
,
FieldInfo
fInfo
)
throws
AtlasException
;
/**
* Generates a limit expression
*
* @param parent
* @param offset
* @param totalRows
* @return
*/
public
abstract
GroovyExpression
generateLimitExpression
(
GroovyExpression
parent
,
int
offset
,
int
totalRows
);
/**
* Generates an order by expression
*
* @param parent
* @param translatedOrderBy
* @param isAscending
* @return
*/
public
abstract
GroovyExpression
generateOrderByExpression
(
GroovyExpression
parent
,
List
<
GroovyExpression
>
translatedOrderBy
,
boolean
isAscending
);
/**
* Returns the Groovy expressions that should be used as the parents when
* translating an order by expression. This is needed because Gremlin 2 and
* 3 handle order by expressions very differently.
*
*/
public
abstract
List
<
GroovyExpression
>
getOrderFieldParents
();
/**
* Returns the expression that represents an anonymous graph traversal.
*
* @return
*/
public
abstract
GroovyExpression
getAnonymousTraversalExpression
();
/**
* Returns an expression representing
*
* @return
*/
public
abstract
GroovyExpression
getFieldInSelect
();
/**
* Generates the expression the serves as the root of the Gremlin query.
* @param s
* @param varExpr variable containing the vertices to traverse
* @return
*/
protected
abstract
GroovyExpression
initialExpression
(
GraphPersistenceStrategies
s
,
GroovyExpression
varExpr
);
/**
* Generates an expression that tests whether the vertex represented by the 'toTest'
* expression represents an instance of the specified type, checking both the type
* and super type names.
*
* @param s
* @param typeName
* @param itRef
* @return
*/
protected
abstract
GroovyExpression
typeTestExpression
(
GraphPersistenceStrategies
s
,
String
typeName
,
GroovyExpression
vertexExpr
);
/**
* Generates a sequence of groovy expressions that filter the vertices to only
* those that match the specified type. If GraphPersistenceStrategies.collectTypeInstancesIntoVar()
* is set, the vertices are put into a variable whose name is geneated from the specified IntSequence.
* The last item in the result will be a graph traversal restricted to only the matching vertices.
*/
public
List
<
GroovyExpression
>
generateTypeTestExpression
(
GraphPersistenceStrategies
s
,
GroovyExpression
parent
,
String
typeName
,
IntSequence
intSeq
)
{
if
(
s
.
collectTypeInstancesIntoVar
())
{
return
typeTestExpressionMultiStep
(
s
,
typeName
,
intSeq
);
}
else
{
return
typeTestExpressionUsingFilter
(
s
,
parent
,
typeName
);
}
}
private
List
<
GroovyExpression
>
typeTestExpressionMultiStep
(
GraphPersistenceStrategies
s
,
String
typeName
,
IntSequence
intSeq
)
{
String
varName
=
"_var_"
+
intSeq
.
next
();
GroovyExpression
varExpr
=
new
IdentifierExpression
(
varName
);
List
<
GroovyExpression
>
result
=
new
ArrayList
<>();
result
.
add
(
newSetVar
(
varName
));
result
.
add
(
fillVarWithTypeInstances
(
s
,
typeName
,
varName
));
result
.
add
(
fillVarWithSubTypeInstances
(
s
,
typeName
,
varName
));
result
.
add
(
initialExpression
(
s
,
varExpr
));
return
result
;
}
private
GroovyExpression
newSetVar
(
String
varName
)
{
GroovyExpression
castExpr
=
new
TypeCoersionExpression
(
new
ListExpression
(),
SET_CLASS
);
return
new
VariableAssignmentExpression
(
varName
,
castExpr
);
}
private
GroovyExpression
fillVarWithTypeInstances
(
GraphPersistenceStrategies
s
,
String
typeName
,
String
fillVar
)
{
GroovyExpression
graphExpr
=
getAllVerticesExpr
();
GroovyExpression
typeAttributeNameExpr
=
new
LiteralExpression
(
s
.
typeAttributeName
());
GroovyExpression
typeNameExpr
=
new
LiteralExpression
(
typeName
);
GroovyExpression
hasExpr
=
new
FunctionCallExpression
(
graphExpr
,
HAS_METHOD
,
typeAttributeNameExpr
,
typeNameExpr
);
GroovyExpression
fillExpr
=
new
FunctionCallExpression
(
hasExpr
,
FILL_METHOD
,
new
IdentifierExpression
(
fillVar
));
return
fillExpr
;
}
private
GroovyExpression
fillVarWithSubTypeInstances
(
GraphPersistenceStrategies
s
,
String
typeName
,
String
fillVar
)
{
GroovyExpression
graphExpr
=
getAllVerticesExpr
();
GroovyExpression
superTypeAttributeNameExpr
=
new
LiteralExpression
(
s
.
superTypeAttributeName
());
GroovyExpression
typeNameExpr
=
new
LiteralExpression
(
typeName
);
GroovyExpression
hasExpr
=
new
FunctionCallExpression
(
graphExpr
,
HAS_METHOD
,
superTypeAttributeNameExpr
,
typeNameExpr
);
GroovyExpression
fillExpr
=
new
FunctionCallExpression
(
hasExpr
,
FILL_METHOD
,
new
IdentifierExpression
(
fillVar
));
return
fillExpr
;
}
private
List
<
GroovyExpression
>
typeTestExpressionUsingFilter
(
GraphPersistenceStrategies
s
,
GroovyExpression
parent
,
String
typeName
)
{
GroovyExpression
itExpr
=
getItVariable
();
GroovyExpression
typeTestExpr
=
typeTestExpression
(
s
,
typeName
,
itExpr
);
GroovyExpression
closureExpr
=
new
ClosureExpression
(
typeTestExpr
);
GroovyExpression
filterExpr
=
new
FunctionCallExpression
(
parent
,
FILTER_METHOD
,
closureExpr
);
return
Collections
.
singletonList
(
filterExpr
);
}
/**
* Generates an expression which checks whether the vertices in the query have
* a field with the given name.
*
* @param parent
* @param fieldName
* @return
*/
public
GroovyExpression
generateUnaryHasExpression
(
GroovyExpression
parent
,
String
fieldName
)
{
return
new
FunctionCallExpression
(
parent
,
HAS_METHOD
,
new
LiteralExpression
(
fieldName
));
}
/**
* Generates a path expression
*
* @param parent
* @return
*/
public
GroovyExpression
generatePathExpression
(
GroovyExpression
parent
)
{
return
new
FunctionCallExpression
(
parent
,
PATH_METHOD
);
}
/**
* Generates the emit expression used in loop expressions.
* @param s
* @param dataType
* @return
*/
protected
GroovyExpression
generateLoopEmitExpression
(
GraphPersistenceStrategies
s
,
IDataType
dataType
)
{
return
typeTestExpression
(
s
,
dataType
.
getName
(),
getCurrentObjectExpression
());
}
/**
* Generates an alias expression
*
* @param parent
* @param alias
* @return
*/
public
GroovyExpression
generateAliasExpression
(
GroovyExpression
parent
,
String
alias
)
{
return
new
FunctionCallExpression
(
parent
,
AS_METHOD
,
new
LiteralExpression
(
alias
));
}
/**
* Generates an expression that gets the vertices adjacent to the vertex in 'parent'
* in the specified direction.
*
* @param parent
* @param dir
* @return
*/
public
GroovyExpression
generateAdjacentVerticesExpression
(
GroovyExpression
parent
,
AtlasEdgeDirection
dir
)
{
return
new
FunctionCallExpression
(
parent
,
getGremlinFunctionName
(
dir
));
}
private
String
getGremlinFunctionName
(
AtlasEdgeDirection
dir
)
{
switch
(
dir
)
{
case
IN:
return
"in"
;
case
OUT:
return
"out"
;
case
BOTH:
return
"both"
;
default
:
throw
new
RuntimeException
(
"Unknown Atlas Edge Direction: "
+
dir
);
}
}
/**
* Generates an expression that gets the vertices adjacent to the vertex in 'parent'
* in the specified direction, following only edges with the given label.
*
* @param parent
* @param dir
* @return
*/
public
GroovyExpression
generateAdjacentVerticesExpression
(
GroovyExpression
parent
,
AtlasEdgeDirection
dir
,
String
label
)
{
return
new
FunctionCallExpression
(
parent
,
getGremlinFunctionName
(
dir
),
new
LiteralExpression
(
label
));
}
/**
* Generates an arithmetic expression, e.g. a + b
*
*/
public
GroovyExpression
generateArithmeticExpression
(
GroovyExpression
left
,
String
operator
,
GroovyExpression
right
)
throws
AtlasException
{
ArithmeticOperator
op
=
ArithmeticOperator
.
lookup
(
operator
);
return
new
ArithmeticExpression
(
left
,
op
,
right
);
}
protected
GroovyExpression
getItVariable
()
{
return
new
IdentifierExpression
(
IT_VARIABLE
);
}
protected
GroovyExpression
getAllVerticesExpr
()
{
GroovyExpression
gExpr
=
getGraph
();
return
new
FunctionCallExpression
(
gExpr
,
V_METHOD
);
}
protected
IdentifierExpression
getGraph
()
{
return
new
IdentifierExpression
(
G_VARIABLE
);
}
protected
GroovyExpression
getCurrentObjectExpression
()
{
return
new
FieldExpression
(
getItVariable
(),
OBJECT_FIELD
);
}
}
\ No newline at end of file
repository/src/main/scala/org/apache/atlas/query/GraphPersistenceStrategies.scala
View file @
69af0ae7
...
...
@@ -21,23 +21,20 @@ package org.apache.atlas.query
import
java.util
import
java.util.Date
import
scala.collection.JavaConversions._
import
scala.collection.JavaConversions.seqAsJavaList
import
scala.language.existentials
import
org.apache.atlas.
query.Expressions.
{
ComparisonExpression
,
ExpressionException
}
import
org.apache.atlas.
groovy.GroovyExpression
import
org.apache.atlas.query.TypeUtils.FieldInfo
import
org.apache.atlas.repository.graph.
{
GraphHelper
,
GraphBackedMetadataRepository
}
import
org.apache.atlas.repository.RepositoryException
import
org.apache.atlas.repository.graph.GraphHelper
import
org.apache.atlas.repository.graphdb._
import
org.apache.atlas.typesystem.
persistence.Id
import
org.apache.atlas.typesystem.
types.DataTypes._
import
org.apache.atlas.typesystem.
ITypedInstance
import
org.apache.atlas.typesystem.
ITypedReferenceableInstance
import
org.apache.atlas.typesystem.persistence.Id
import
org.apache.atlas.typesystem.types._
import
org.apache.atlas.typesystem.
{
ITypedInstance
,
ITypedReferenceableInstance
}
import
scala.collection.JavaConversions._
import
scala.collection.mutable
import
scala.collection.mutable.ArrayBuffer
import
org.apache.atlas.typesystem.types.DataTypes._
/**
* Represents the Bridge between the QueryProcessor and the Graph Persistence scheme used.
...
...
@@ -47,19 +44,19 @@ import scala.collection.mutable.ArrayBuffer
* - how are attribute names mapped to Property Keys in Vertices.
*
* This is a work in progress.
*
*
*/
trait
GraphPersistenceStrategies
{
@throws
(
classOf
[
RepositoryException
])
def
getGraph
()
:
AtlasGraph
[
_
,
_
]
def
getSupportedGremlinVersion
()
:
GremlinVersion
=
getGraph
().
getSupportedGremlinVersion
;
def
generatePersisentToLogicalConversionExpression
(
expr
:
String
,
t
:
IDataType
[
_
])
:
String
=
getGraph
().
generatePersisentToLogicalConversionExpression
(
expr
,
t
);
def
generatePersisentToLogicalConversionExpression
(
expr
:
GroovyExpression
,
t
:
IDataType
[
_
])
:
GroovyExpression
=
getGraph
().
generatePersisentToLogicalConversionExpression
(
expr
,
t
);
def
isPropertyValueConversionNeeded
(
attrType
:
IDataType
[
_
])
:
Boolean
=
getGraph
().
isPropertyValueConversionNeeded
(
attrType
);
def
initialQueryCondition
=
if
(
getGraph
().
requiresInitialIndexedPredicate
())
{
s
""".${getGraph().getInitialIndexedPredicate}"""
}
else
{
""
};
def
addInitialQueryCondition
(
parent
:
GroovyExpression
)
:
GroovyExpression
=
if
(
getGraph
().
requiresInitialIndexedPredicate
())
{
getGraph
().
getInitialIndexedPredicate
(
parent
)
}
else
{
parent
};
/**
* Name of attribute used to store typeName in vertex
*/
...
...
@@ -87,11 +84,12 @@ trait GraphPersistenceStrategies {
def
traitLabel
(
cls
:
IDataType
[
_
],
traitName
:
String
)
:
String
def
instanceToTraitEdgeDirection
:
String
=
"out"
def
traitToInstanceEdgeDirection
=
instanceToTraitEdgeDirection
match
{
case
"out"
=>
"in"
case
"in"
=>
"out"
case
x
=>
x
def
instanceToTraitEdgeDirection
:
AtlasEdgeDirection
=
AtlasEdgeDirection
.
OUT
;
def
traitToInstanceEdgeDirection
:
AtlasEdgeDirection
=
instanceToTraitEdgeDirection
match
{
case
AtlasEdgeDirection
.
OUT
=>
AtlasEdgeDirection
.
IN
;
case
AtlasEdgeDirection
.
IN
=>
AtlasEdgeDirection
.
OUT
;
case
x
=>
AtlasEdgeDirection
.
IN
;
}
/**
...
...
@@ -115,27 +113,6 @@ trait GraphPersistenceStrategies {
case
FieldInfo
(
dataType
,
null
,
null
,
traitName
)
=>
traitLabel
(
dataType
,
traitName
)
}
def
fieldPrefixInSelect
()
:
String
=
{
if
(
getSupportedGremlinVersion
()
==
GremlinVersion
.
THREE
)
{
//this logic is needed to remove extra results from
//what is emitted by repeat loops. Technically
//for queries that don't have a loop in them we could just use "it"
//the reason for this is that in repeat loops with an alias,
//although the alias gets set to the right value, for some
//reason the select actually includes all vertices that were traversed
//through in the loop. In these cases, we only want the last vertex
//traversed in the loop to be selected. The logic here handles that
//case by converting the result to a list and just selecting the
//last item from it.
"((it as Vertex[]) as List<Vertex>).last()"
}
else
{
"it"
}
}
/**
* extract the Id from a Vertex.
* @param dataTypeNm the dataType of the instance that the given vertex represents
...
...
@@ -146,50 +123,7 @@ trait GraphPersistenceStrategies {
def
constructInstance
[
U
](
dataType
:
IDataType
[
U
],
v
:
java.lang.Object
)
:
U
def
gremlinCompOp
(
op
:
ComparisonExpression
)
=
{
if
(
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
gremlin2CompOp
(
op
);
}
else
{
gremlin3CompOp
(
op
);
}
}
def
gremlinPrimitiveOp
(
op
:
ComparisonExpression
)
=
op
.
symbol
match
{
case
"="
=>
"=="
case
"!="
=>
"!="
case
">"
=>
">"
case
">="
=>
">="
case
"<"
=>
"<"
case
"<="
=>
"<="
case
_
=>
throw
new
ExpressionException
(
op
,
"Comparison operator not supported in Gremlin"
)
}
private
def
gremlin2CompOp
(
op
:
ComparisonExpression
)
=
op
.
symbol
match
{
case
"="
=>
"T.eq"
case
"!="
=>
"T.neq"
case
">"
=>
"T.gt"
case
">="
=>
"T.gte"
case
"<"
=>
"T.lt"
case
"<="
=>
"T.lte"
case
_
=>
throw
new
ExpressionException
(
op
,
"Comparison operator not supported in Gremlin"
)
}
private
def
gremlin3CompOp
(
op
:
ComparisonExpression
)
=
op
.
symbol
match
{
case
"="
=>
"eq"
case
"!="
=>
"neq"
case
">"
=>
"gt"
case
">="
=>
"gte"
case
"<"
=>
"lt"
case
"<="
=>
"lte"
case
_
=>
throw
new
ExpressionException
(
op
,
"Comparison operator not supported in Gremlin"
)
}
def
loopObjectExpression
(
dataType
:
IDataType
[
_
])
=
{
_typeTestExpression
(
dataType
.
getName
,
"it.object"
)
}
def
addGraphVertexPrefix
(
preStatements
:
Traversable
[
String
])
=
!
collectTypeInstancesIntoVar
def
addGraphVertexPrefix
(
preStatements
:
Traversable
[
GroovyExpression
])
=
!
collectTypeInstancesIntoVar
/**
* Controls behavior of how instances of a Type are discovered.
...
...
@@ -213,76 +147,14 @@ trait GraphPersistenceStrategies {
*/
def
collectTypeInstancesIntoVar
=
true
def
typeTestExpression
(
typeName
:
String
,
intSeq
:
IntSequence
)
:
Seq
[
String
]
=
{
if
(
collectTypeInstancesIntoVar
)
typeTestExpressionMultiStep
(
typeName
,
intSeq
)
else
typeTestExpressionUsingFilter
(
typeName
)
}
private
def
typeTestExpressionUsingFilter
(
typeName
:
String
)
:
Seq
[
String
]
=
{
Seq
(
s
"""filter${_typeTestExpression(typeName, "it")}"""
)
}
/**
* type test expression that ends up in the emit clause in
* loop/repeat steps and a few other places
*/
private
def
_typeTestExpression
(
typeName
:
String
,
itRef
:
String
)
:
String
=
{
if
(
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
s
"""{(${itRef}.'${typeAttributeName}' == '${typeName}') |
| (${itRef}.'${superTypeAttributeName}' ?
| ${itRef}.'${superTypeAttributeName}'.contains('${typeName}') : false)}"""
.
stripMargin
.
replace
(
System
.
getProperty
(
"line.separator"
),
""
)
}
else
{
//gremlin 3
s
"""has('${typeAttributeName}',eq('${typeName}')).or().has('${superTypeAttributeName}',eq('${typeName}'))"""
}
}
private
def
propertyValueSet
(
vertexRef
:
String
,
attrName
:
String
)
:
String
=
{
s
"""org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils.set(${vertexRef}.values('${attrName})"""
}
private
def
typeTestExpressionMultiStep
(
typeName
:
String
,
intSeq
:
IntSequence
)
:
Seq
[
String
]
=
{
val
varName
=
s
"_var_${intSeq.next}"
Seq
(
newSetVar
(
varName
),
fillVarWithTypeInstances
(
typeName
,
varName
),
fillVarWithSubTypeInstances
(
typeName
,
varName
),
if
(
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
s
"$varName._()"
}
else
{
//this bit of groovy magic converts the set of vertices in varName into
//a String containing the ids of all the vertices. This becomes the argument
//to g.V(). This is needed because Gremlin 3 does not support
// _()
//s"g.V(${varName}.collect{it.id()} as String[])"
s
"g.V(${varName} as Object[])${initialQueryCondition}"
}
)
}
private
def
newSetVar
(
varName
:
String
)
=
s
"def $varName = [] as Set"
private
def
fillVarWithTypeInstances
(
typeName
:
String
,
fillVar
:
String
)
=
{
s
"""g.V().has("${typeAttributeName}", "${typeName}").fill($fillVar)"""
}
private
def
fillVarWithSubTypeInstances
(
typeName
:
String
,
fillVar
:
String
)
=
{
s
"""g.V().has("${superTypeAttributeName}", "${typeName}").fill($fillVar)"""
}
}
import
scala.language.existentials
;
import
org.apache.atlas.repository.RepositoryException
import
org.apache.atlas.repository.RepositoryException
import
org.apache.atlas.repository.RepositoryException
import
org.apache.atlas.repository.RepositoryException
case
class
GraphPersistenceStrategy1
(
g
:
AtlasGraph
[
_
,
_
])
extends
GraphPersistenceStrategies
{
...
...
@@ -293,8 +165,8 @@ case class GraphPersistenceStrategy1(g: AtlasGraph[_,_]) extends GraphPersistenc
override
def
getGraph
()
:
AtlasGraph
[
_
,
_
]
=
{
return
g
;
}
}
def
edgeLabel
(
dataType
:
IDataType
[
_
],
aInfo
:
AttributeInfo
)
=
s
"__${dataType.getName}.${aInfo.name}"
def
edgeLabel
(
propertyName
:
String
)
=
s
"__${propertyName}"
...
...
@@ -458,8 +330,6 @@ case class GraphPersistenceStrategy1(g: AtlasGraph[_,_]) extends GraphPersistenc
}
}
private
def
mapVertexToCollectionEntry
(
instanceVertex
:
AtlasVertex
[
_
,
_
],
attributeInfo
:
AttributeInfo
,
elementType
:
IDataType
[
_
],
i
:
ITypedInstance
,
value
:
Any
)
:
Any
=
{
elementType
.
getTypeCategory
match
{
case
DataTypes
.
TypeCategory
.
PRIMITIVE
=>
value
...
...
@@ -474,5 +344,6 @@ case class GraphPersistenceStrategy1(g: AtlasGraph[_,_]) extends GraphPersistenc
throw
new
UnsupportedOperationException
(
s
"load for ${attributeInfo.dataType()} not supported"
)
}
}
}
repository/src/main/scala/org/apache/atlas/query/GremlinQuery.scala
View file @
69af0ae7
...
...
@@ -18,30 +18,61 @@
package
org.apache.atlas.query
import
java.lang.Boolean
import
java.lang.Byte
import
java.lang.Double
import
java.lang.Float
import
java.lang.Integer
import
java.lang.Long
import
java.lang.Short
import
java.util.ArrayList
import
scala.collection.JavaConversions.asScalaBuffer
import
scala.collection.JavaConversions.bufferAsJavaList
import
scala.collection.mutable
import
scala.collection.mutable.ArrayBuffer
import
org.apache.atlas.query.TypeUtils.FieldInfo
;
import
org.apache.atlas.query.Expressions._
import
org.apache.atlas.repository.graphdb.GremlinVersion
import
org.apache.atlas.gremlin.GremlinExpressionFactory
import
org.apache.atlas.groovy.CastExpression
import
org.apache.atlas.groovy.CodeBlockExpression
import
org.apache.atlas.groovy.FunctionCallExpression
import
org.apache.atlas.groovy.GroovyExpression
import
org.apache.atlas.groovy.GroovyGenerationContext
import
org.apache.atlas.groovy.IdentifierExpression
import
org.apache.atlas.groovy.ListExpression
import
org.apache.atlas.groovy.LiteralExpression
import
org.apache.atlas.query.Expressions.AliasExpression
import
org.apache.atlas.query.Expressions.ArithmeticExpression
import
org.apache.atlas.query.Expressions.BackReference
import
org.apache.atlas.query.Expressions.ClassExpression
import
org.apache.atlas.query.Expressions.ComparisonExpression
import
org.apache.atlas.query.Expressions.Expression
import
org.apache.atlas.query.Expressions.ExpressionException
import
org.apache.atlas.query.Expressions.FieldExpression
import
org.apache.atlas.query.Expressions.FilterExpression
import
org.apache.atlas.query.Expressions.InstanceExpression
import
org.apache.atlas.query.Expressions.LimitExpression
import
org.apache.atlas.query.Expressions.ListLiteral
import
org.apache.atlas.query.Expressions.Literal
import
org.apache.atlas.query.Expressions.LogicalExpression
import
org.apache.atlas.query.Expressions.LoopExpression
import
org.apache.atlas.query.Expressions.OrderExpression
import
org.apache.atlas.query.Expressions.PathExpression
import
org.apache.atlas.query.Expressions.SelectExpression
import
org.apache.atlas.query.Expressions.TraitExpression
import
org.apache.atlas.query.Expressions.TraitInstanceExpression
import
org.apache.atlas.query.Expressions.hasFieldLeafExpression
import
org.apache.atlas.query.Expressions.hasFieldUnaryExpression
import
org.apache.atlas.query.Expressions.id
import
org.apache.atlas.query.Expressions.isTraitLeafExpression
import
org.apache.atlas.query.Expressions.isTraitUnaryExpression
import
org.apache.atlas.repository.RepositoryException
import
org.apache.atlas.repository.graphdb.AtlasEdgeDirection
import
org.apache.atlas.typesystem.types.DataTypes
import
org.apache.atlas.typesystem.types.DataTypes.TypeCategory
import
org.apache.atlas.typesystem.types.IDataType
import
org.apache.commons.lang.StringEscapeUtils
import
org.apache.atlas.typesystem.types.TypeSystem
import
org.apache.atlas.typesystem.types.AttributeInfo
import
org.joda.time.format.ISODateTimeFormat
import
org.apache.atlas.typesystem.types.DataTypes.BigDecimalType
import
org.apache.atlas.typesystem.types.DataTypes.ByteType
import
org.apache.atlas.typesystem.types.DataTypes.BooleanType
import
org.apache.atlas.typesystem.types.DataTypes.DateType
import
org.apache.atlas.typesystem.types.DataTypes.BigIntegerType
import
org.apache.atlas.typesystem.types.DataTypes.IntType
import
org.apache.atlas.typesystem.types.DataTypes.StringType
import
org.apache.atlas.typesystem.types.DataTypes.LongType
import
org.apache.atlas.typesystem.types.DataTypes.DoubleType
import
org.apache.atlas.typesystem.types.DataTypes.FloatType
import
org.apache.atlas.typesystem.types.DataTypes.ShortType
trait
IntSequence
{
def
next
:
Int
...
...
@@ -127,7 +158,7 @@ trait SelectExpressionHandling {
/**
* For each Output Column in the SelectExpression compute the ArrayList(Src) this maps to and the position within
* this list.
*
*
* @param sel
* @return
*/
...
...
@@ -151,8 +182,8 @@ class GremlinTranslator(expr: Expression,
gPersistenceBehavior
:
GraphPersistenceStrategies
)
extends
SelectExpressionHandling
{
val
preStatements
=
ArrayBuffer
[
String
]()
val
postStatements
=
ArrayBuffer
[
String
]()
val
preStatements
=
ArrayBuffer
[
GroovyExpression
]()
val
postStatements
=
ArrayBuffer
[
GroovyExpression
]()
val
wrapAndRule
:
PartialFunction
[
Expression
,
Expression
]
=
{
case
f
:
FilterExpression
if
!f.condExpr.isInstanceOf
[
LogicalExpression
]
=>
...
...
@@ -216,351 +247,287 @@ class GremlinTranslator(expr: Expression,
}
}
def
typeTestExpression
(
typeName
:
String
)
:
String
=
{
val
stats
=
gPersistenceBehavior
.
typeTestExpression
(
escape
(
typeName
),
counter
)
def
typeTestExpression
(
parent
:
GroovyExpression
,
typeName
:
String
)
:
GroovyExpression
=
{
val
stats
=
GremlinExpressionFactory
.
INSTANCE
.
generateTypeTestExpression
(
gPersistenceBehavior
,
parent
,
typeName
,
counter
)
preStatements
++=
stats
.
init
stats
.
last
}
def
escape
(
str
:
String
)
:
String
=
{
if
(
str
!=
null
)
{
return
str
.
replace
(
"\""
,
"\\\""
).
replace
(
"$"
,
"\\$"
);
}
str
val
QUOTE
=
"\""
;
private
def
cleanStringLiteral
(
l
:
Literal
[
_
])
:
String
=
{
return
l
.
toString
.
stripPrefix
(
QUOTE
).
stripSuffix
(
QUOTE
);
}
private
def
genQuery
(
expr
:
Expression
,
inSelect
:
Boolean
)
:
String
=
expr
match
{
case
ClassExpression
(
clsName
)
=>
typeTestExpression
(
clsName
)
case
TraitExpression
(
clsName
)
=>
typeTestExpression
(
clsName
)
private
def
genQuery
(
parent
:
GroovyExpression
,
expr
:
Expression
,
inSelect
:
Boolean
)
:
GroovyExpression
=
expr
match
{
case
ClassExpression
(
clsName
)
=>
typeTestExpression
(
parent
,
clsName
)
case
TraitExpression
(
clsName
)
=>
typeTestExpression
(
parent
,
clsName
)
case
fe
@FieldExpression
(
fieldName
,
fInfo
,
child
)
if
fe
.
dataType
.
getTypeCategory
==
TypeCategory
.
PRIMITIVE
||
fe
.
dataType
.
getTypeCategory
==
TypeCategory
.
ARRAY
=>
{
val
fN
=
"\""
+
gPersistenceBehavior
.
fieldNameInVertex
(
fInfo
.
dataType
,
fInfo
.
attrInfo
)
+
"\""
genPropertyAccessExpr
(
child
,
fInfo
,
fN
,
inSelect
)
}
val
fN
=
gPersistenceBehavior
.
fieldNameInVertex
(
fInfo
.
dataType
,
fInfo
.
attrInfo
)
val
childExpr
=
translateOptChild
(
parent
,
child
,
inSelect
);
return
GremlinExpressionFactory
.
INSTANCE
.
generateFieldExpression
(
childExpr
,
fInfo
,
fN
,
inSelect
);
}
case
fe
@FieldExpression
(
fieldName
,
fInfo
,
child
)
if
fe
.
dataType
.
getTypeCategory
==
TypeCategory
.
CLASS
||
fe
.
dataType
.
getTypeCategory
==
TypeCategory
.
STRUCT
=>
{
val
direction
=
if
(
fInfo
.
isReverse
)
"in"
else
"out"
val
childExpr
=
translateOptChild
(
parent
,
child
,
inSelect
);
val
direction
=
if
(
fInfo
.
isReverse
)
AtlasEdgeDirection
.
IN
else
AtlasEdgeDirection
.
OUT
val
edgeLbl
=
gPersistenceBehavior
.
edgeLabel
(
fInfo
)
val
step
=
s
"""$direction("$edgeLbl")"""
generateAndPrependExpr
(
child
,
inSelect
,
s
"""$step"""
)
}
return
GremlinExpressionFactory
.
INSTANCE
.
generateAdjacentVerticesExpression
(
childExpr
,
direction
,
edgeLbl
)
}
case
fe
@FieldExpression
(
fieldName
,
fInfo
,
child
)
if
fInfo
.
traitName
!=
null
=>
{
val
childExpr
=
translateOptChild
(
parent
,
child
,
inSelect
);
val
direction
=
gPersistenceBehavior
.
instanceToTraitEdgeDirection
val
edgeLbl
=
gPersistenceBehavior
.
edgeLabel
(
fInfo
)
val
step
=
s
"""$direction("$edgeLbl")"""
generateAndPrependExpr
(
child
,
inSelect
,
s
"""$step"""
)
return
GremlinExpressionFactory
.
INSTANCE
.
generateAdjacentVerticesExpression
(
childExpr
,
direction
,
edgeLbl
)
}
case
c
@ComparisonExpression
(
symb
,
f
@FieldExpression
(
fieldName
,
fInfo
,
ch
),
l
)
=>
{
return
genHasPredicate
(
ch
,
fInfo
,
fieldName
,
inSelect
,
c
,
l
)
val
qualifiedPropertyName
=
s
"${gPersistenceBehavior.fieldNameInVertex(fInfo.dataType, fInfo.attrInfo)}"
val
childExpr
=
translateOptChild
(
parent
,
ch
,
inSelect
)
val
persistentExprValue
:
GroovyExpression
=
if
(
l
.
isInstanceOf
[
Literal
[
_
]])
{
translateLiteralValue
(
fInfo
.
attrInfo
.
dataType
,
l
.
asInstanceOf
[
Literal
[
_
]]);
}
else
{
genQuery
(
null
,
l
,
inSelect
);
}
return
GremlinExpressionFactory
.
INSTANCE
.
generateHasExpression
(
gPersistenceBehavior
,
childExpr
,
qualifiedPropertyName
,
c
.
symbol
,
persistentExprValue
,
fInfo
);
}
case
fil
@FilterExpression
(
child
,
condExpr
)
=>
{
s
"${genQuery(child, inSelect)}.${genQuery(condExpr, inSelect)}"
val
newParent
=
genQuery
(
parent
,
child
,
inSelect
);
return
genQuery
(
newParent
,
condExpr
,
inSelect
);
}
case
l
@LogicalExpression
(
symb
,
children
)
=>
{
if
(
gPersistenceBehavior
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
THREE
)
{
if
(
children
.
length
==
1
)
{
//gremlin 3 treats one element expressions as 'false'. Avoid
//creating a boolean expression in this case. Inline the expression
//note: we can't simply omit it, since it will cause us to traverse the edge!
//use 'where' instead
var
child
:
Expression
=
children
.
head
;
//if child is a back expression, that expression becomes an argument to where
return
s
"""where(${genQuery(child, inSelect)})"""
;
}
else
{
// Gremlin 3 does not support _() syntax
//
return
s
"""$symb${children.map( genQuery(_, inSelect)).mkString("(", ",", ")")}"""
}
}
else
{
s
"""$symb${children.map("_()." + genQuery(_, inSelect)).mkString("(", ",", ")")}"""
}
val
translatedChildren
:
java.util.List
[
GroovyExpression
]
=
translateList
(
children
,
true
,
inSelect
);
return
GremlinExpressionFactory
.
INSTANCE
.
generateLogicalExpression
(
parent
,
symb
,
translatedChildren
);
}
case
sel
@SelectExpression
(
child
,
selList
)
=>
{
val
m
=
groupSelectExpressionsBySrc
(
sel
)
var
srcNamesList
:
List
[
String
]
=
List
()
var
srcExprsList
:
List
[
List
[
String
]]
=
List
()
var
srcNamesList
:
java.util.List
[
LiteralExpression
]
=
new
Array
List
()
var
srcExprsList
:
List
[
java.util.List
[
GroovyExpression
]]
=
List
()
val
it
=
m
.
iterator
while
(
it
.
hasNext
)
{
val
(
src
,
selExprs
)
=
it
.
next
srcNamesList
=
srcNamesList
:+
s
""""$src""""
srcExprsList
=
srcExprsList
:+
selExprs
.
map
{
selExpr
=>
genQuery
(
selExpr
,
true
)
}
srcNamesList
.
add
(
new
LiteralExpression
(
src
));
val
translatedSelExprs
:
java.util.List
[
GroovyExpression
]
=
translateList
(
selExprs
,
false
,
true
);
srcExprsList
=
srcExprsList
:+
translatedSelExprs
}
val
srcExprsStringList
=
srcExprsList
.
map
{
_
.
mkString
(
"["
,
","
,
"]"
)
val
srcExprsStringList
:
java.util.List
[
GroovyExpression
]
=
new
ArrayList
();
srcExprsList
.
foreach
{
it
=>
srcExprsStringList
.
add
(
new
ListExpression
(
it
));
}
if
(
gPersistenceBehavior
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
val
srcNamesString
=
srcNamesList
.
mkString
(
"["
,
","
,
"]"
)
val
srcExprsString
=
srcExprsStringList
.
foldLeft
(
""
)(
_
+
"{"
+
_
+
"}"
)
s
"${genQuery(child, inSelect)}.select($srcNamesString)$srcExprsString"
}
else
{
//gremlin 3
val
srcNamesString
=
srcNamesList
.
mkString
(
""
,
","
,
""
)
val
srcExprsString
=
srcExprsStringList
.
foldLeft
(
""
)(
_
+
".by({"
+
_
+
"} as Function)"
)
s
"${genQuery(child, inSelect)}.select($srcNamesString)$srcExprsString"
}
val
childExpr
=
genQuery
(
parent
,
child
,
inSelect
)
return
GremlinExpressionFactory
.
INSTANCE
.
generateSelectExpression
(
childExpr
,
srcNamesList
,
srcExprsStringList
);
}
case
loop
@LoopExpression
(
input
,
loopExpr
,
t
)
=>
{
if
(
gPersistenceBehavior
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
val
inputQry
=
genQuery
(
input
,
inSelect
)
val
loopingPathGExpr
=
genQuery
(
loopExpr
,
inSelect
)
val
loopGExpr
=
s
"""loop("${input.asInstanceOf[AliasExpression].alias}")"""
val
untilCriteria
=
if
(
t
.
isDefined
)
s
"{it.loops < ${t.get.value}}"
else
"{it.path.contains(it.object)?false:true}"
val
loopObjectGExpr
=
gPersistenceBehavior
.
loopObjectExpression
(
input
.
dataType
)
val
enablePathExpr
=
s
".enablePath()"
s
"""${inputQry}.${loopingPathGExpr}.${loopGExpr}${untilCriteria}${loopObjectGExpr}${enablePathExpr}"""
val
times
:
Integer
=
if
(
t
.
isDefined
)
{
t
.
get
.
rawValue
.
asInstanceOf
[
Integer
]
}
else
{
//gremlin 3 - TODO - add support for circular lineage
val
inputQry
=
genQuery
(
input
,
inSelect
)
val
repeatExpr
=
s
"""repeat(__.${genQuery(loopExpr, inSelect)})"""
val
optTimesExpr
=
if
(
t
.
isDefined
)
s
".times(${t.get.value})"
else
""
val
emitExpr
=
s
""".emit(${gPersistenceBehavior.loopObjectExpression(input.dataType)})"""
s
"""${inputQry}.${repeatExpr}${optTimesExpr}${emitExpr}"""
null
.
asInstanceOf
[
Integer
]
}
val
alias
=
input
.
asInstanceOf
[
AliasExpression
].
alias
;
val
inputQry
=
genQuery
(
parent
,
input
,
inSelect
)
val
translatedLoopExpr
=
genQuery
(
GremlinExpressionFactory
.
INSTANCE
.
getLoopExpressionParent
(
inputQry
),
loopExpr
,
inSelect
);
return
GremlinExpressionFactory
.
INSTANCE
.
generateLoopExpression
(
inputQry
,
gPersistenceBehavior
,
input
.
dataType
,
translatedLoopExpr
,
alias
,
times
);
}
case
BackReference
(
alias
,
_
,
_
)
=>
{
if
(
inSelect
)
{
gPersistenceBehavior
.
fieldPrefixInSelect
()
}
else
{
if
(
gPersistenceBehavior
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
s
"""back("$alias")"""
}
else
{
s
"""select("$alias")"""
}
}
return
GremlinExpressionFactory
.
INSTANCE
.
generateBackReferenceExpression
(
parent
,
inSelect
,
alias
);
}
case
AliasExpression
(
child
,
alias
)
=>
{
var
childExpr
=
genQuery
(
parent
,
child
,
inSelect
);
return
GremlinExpressionFactory
.
INSTANCE
.
generateAliasExpression
(
childExpr
,
alias
);
}
case
isTraitLeafExpression
(
traitName
,
Some
(
clsExp
))
=>
{
val
label
=
gPersistenceBehavior
.
traitLabel
(
clsExp
.
dataType
,
traitName
);
return
GremlinExpressionFactory
.
INSTANCE
.
generateAdjacentVerticesExpression
(
parent
,
AtlasEdgeDirection
.
OUT
,
label
);
}
case
isTraitUnaryExpression
(
traitName
,
child
)
=>
{
val
label
=
gPersistenceBehavior
.
traitLabel
(
child
.
dataType
,
traitName
);
return
GremlinExpressionFactory
.
INSTANCE
.
generateAdjacentVerticesExpression
(
parent
,
AtlasEdgeDirection
.
OUT
,
label
);
}
case
AliasExpression
(
child
,
alias
)
=>
s
"""${genQuery(child, inSelect)}.as("$alias")"""
case
isTraitLeafExpression
(
traitName
,
Some
(
clsExp
))
=>
s
"""out("${gPersistenceBehavior.traitLabel(clsExp.dataType, traitName)}")"""
case
isTraitUnaryExpression
(
traitName
,
child
)
=>
s
"""out("${gPersistenceBehavior.traitLabel(child.dataType, traitName)}")"""
case
hasFieldLeafExpression
(
fieldName
,
clsExp
)
=>
clsExp
match
{
case
None
=>
s
"""has("$fieldName")"""
case
None
=>
GremlinExpressionFactory
.
INSTANCE
.
generateUnaryHasExpression
(
parent
,
fieldName
)
case
Some
(
x
)
=>
{
val
fi
=
TypeUtils
.
resolveReference
(
clsExp
.
get
.
dataType
,
fieldName
);
if
(!
fi
.
isDefined
)
{
s
"""has("$fieldName")"""
return
GremlinExpressionFactory
.
INSTANCE
.
generateUnaryHasExpression
(
parent
,
fieldName
);
}
else
{
s
"""has("${gPersistenceBehavior.fieldNameInVertex(fi.get.dataType, fi.get.attrInfo)}")"""
val
fName
=
gPersistenceBehavior
.
fieldNameInVertex
(
fi
.
get
.
dataType
,
fi
.
get
.
attrInfo
)
return
GremlinExpressionFactory
.
INSTANCE
.
generateUnaryHasExpression
(
parent
,
fName
);
}
}
}
case
hasFieldUnaryExpression
(
fieldName
,
child
)
=>
s
"""${genQuery(child, inSelect)}.has("$fieldName")"""
case
ArithmeticExpression
(
symb
,
left
,
right
)
=>
s
"${genQuery(left, inSelect)} $symb ${genQuery(right, inSelect)}"
case
l
:
Literal
[
_
]
=>
l
.
toString
case
list
:
ListLiteral
[
_
]
=>
list
.
toString
val
childExpr
=
genQuery
(
parent
,
child
,
inSelect
);
return
GremlinExpressionFactory
.
INSTANCE
.
generateUnaryHasExpression
(
childExpr
,
fieldName
);
case
ArithmeticExpression
(
symb
,
left
,
right
)
=>
{
val
leftExpr
=
genQuery
(
parent
,
left
,
inSelect
);
val
rightExpr
=
genQuery
(
parent
,
right
,
inSelect
);
return
GremlinExpressionFactory
.
INSTANCE
.
generateArithmeticExpression
(
leftExpr
,
symb
,
rightExpr
);
}
case
l
:
Literal
[
_
]
=>
{
if
(
parent
!=
null
)
{
return
new
org
.
apache
.
atlas
.
groovy
.
FieldExpression
(
parent
,
cleanStringLiteral
(
l
));
}
return
translateLiteralValue
(
l
.
dataType
,
l
);
}
case
list
:
ListLiteral
[
_
]
=>
{
val
values
:
java.util.List
[
GroovyExpression
]
=
translateList
(
list
.
rawValue
,
false
,
inSelect
);
return
new
ListExpression
(
values
);
}
case
in
@TraitInstanceExpression
(
child
)
=>
{
val
direction
=
gPersistenceBehavior
.
traitToInstanceEdgeDirection
s
"${genQuery(child, inSelect)}.$direction()"
val
childExpr
=
genQuery
(
parent
,
child
,
inSelect
);
val
direction
=
gPersistenceBehavior
.
traitToInstanceEdgeDirection
;
return
GremlinExpressionFactory
.
INSTANCE
.
generateAdjacentVerticesExpression
(
childExpr
,
direction
);
}
case
in
@InstanceExpression
(
child
)
=>
{
s
"${genQuery(child, inSelect)}"
return
genQuery
(
parent
,
child
,
inSelect
);
}
case
pe
@PathExpression
(
child
)
=>
{
if
(
gPersistenceBehavior
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
s
"${genQuery(child, inSelect)}.path"
}
else
{
s
"${genQuery(child, inSelect)}.path()"
}
val
childExpr
=
genQuery
(
parent
,
child
,
inSelect
)
return
GremlinExpressionFactory
.
INSTANCE
.
generatePathExpression
(
childExpr
);
}
case
order
@OrderExpression
(
child
,
odr
,
asc
)
=>
{
var
orderby
=
""
var
orderExpression
=
odr
if
(
odr
.
isInstanceOf
[
BackReference
])
{
orderExpression
=
odr
.
asInstanceOf
[
BackReference
].
reference
if
(
odr
.
isInstanceOf
[
BackReference
])
{
orderExpression
=
odr
.
asInstanceOf
[
BackReference
].
reference
}
else
if
(
odr
.
isInstanceOf
[
AliasExpression
])
{
else
if
(
odr
.
isInstanceOf
[
AliasExpression
])
{
orderExpression
=
odr
.
asInstanceOf
[
AliasExpression
].
child
}
val
orderbyProperty
=
genQuery
(
orderExpression
,
false
)
if
(
gPersistenceBehavior
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
val
bProperty
=
s
"it.b.$orderbyProperty"
val
aProperty
=
s
"it.a.$orderbyProperty"
val
aCondition
=
s
"($aProperty != null ? $aProperty.toLowerCase(): $aProperty)"
val
bCondition
=
s
"($bProperty != null ? $bProperty.toLowerCase(): $bProperty)"
orderby
=
asc
match
{
//builds a closure comparison function based on provided order by clause in DSL. This will be used to sort the results by gremlin order pipe.
//Ordering is case insensitive.
case
false
=>
s
"order{$bCondition <=> $aCondition}"
//descending
case
_
=>
s
"order{$aCondition <=> $bCondition}"
}
}
else
{
val
orderbyProperty
=
genQuery
(
orderExpression
,
true
);
val
aPropertyExpr
=
gremlin3ToLowerCase
(
"a"
);
val
bPropertyExpr
=
gremlin3ToLowerCase
(
"b"
);
orderby
=
asc
match
{
//builds a closure comparison function based on provided order by clause in DSL. This will be used to sort the results by gremlin order pipe.
//Ordering is case insensitive.
case
false
=>
s
"""order().by({$orderbyProperty'}, { a,b -> $bPropertyExpr <=> $aPropertyExpr })"""
case
_
=>
s
"""order().by({$orderbyProperty},{ a,b -> $aPropertyExpr <=> $bPropertyExpr })"""
}
val
childExpr
=
genQuery
(
parent
,
child
,
inSelect
);
var
orderByParents
:
java.util.List
[
GroovyExpression
]
=
GremlinExpressionFactory
.
INSTANCE
.
getOrderFieldParents
();
val
translatedParents
:
java.util.List
[
GroovyExpression
]
=
new
ArrayList
[
GroovyExpression
]();
var
translatedOrderParents
=
orderByParents
.
foreach
{
it
=>
translatedParents
.
add
(
genQuery
(
it
,
orderExpression
,
false
));
}
s
"""${genQuery(child, inSelect)}.$orderby"""
return
GremlinExpressionFactory
.
INSTANCE
.
generateOrderByExpression
(
childExpr
,
translatedParents
,
asc
);
}
case
limitOffset
@LimitExpression
(
child
,
limit
,
offset
)
=>
{
if
(
gPersistenceBehavior
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
val
totalResultRows
=
limit
.
value
+
offset
.
value
s
"""${genQuery(child, inSelect)} [$offset..<$totalResultRows]"""
}
else
{
val
totalResultRows
=
limit
.
value
+
offset
.
value
s
"""${genQuery(child, inSelect)}.range($offset,$totalResultRows)"""
}
val
childExpr
=
genQuery
(
parent
,
child
,
inSelect
);
val
totalResultRows
=
limit
.
value
+
offset
.
value
;
return
GremlinExpressionFactory
.
INSTANCE
.
generateLimitExpression
(
childExpr
,
offset
.
value
,
totalResultRows
);
}
case
x
=>
throw
new
GremlinTranslationException
(
x
,
"expression not yet supported"
)
}
def
gremlin3ToLowerCase
(
varName
:
String
)
:
String
=
{
s
"""($varName != null ? $varName.toString().toLowerCase() : null)"""
}
def
genPropertyAccessExpr
(
e
:
Option
[
Expression
],
fInfo
:
FieldInfo
,
quotedPropertyName
:
String
,
inSelect
:
Boolean
)
:
String
=
{
if
(
gPersistenceBehavior
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
generateAndPrependExpr
(
e
,
inSelect
,
s
"""$quotedPropertyName"""
)
}
else
{
val
attrInfo
:
AttributeInfo
=
fInfo
.
attrInfo
;
val
attrType
:
IDataType
[
_
]
=
attrInfo
.
dataType
;
if
(
inSelect
)
{
val
expr
=
generateAndPrependExpr
(
e
,
inSelect
,
s
"""property($quotedPropertyName).orElse(null)"""
);
return
gPersistenceBehavior
.
generatePersisentToLogicalConversionExpression
(
expr
,
attrType
);
}
else
{
val
unmapped
=
s
"""values($quotedPropertyName)"""
val
expr
=
if
(
gPersistenceBehavior
.
isPropertyValueConversionNeeded
(
attrType
))
{
val
conversionFunction
=
gPersistenceBehavior
.
generatePersisentToLogicalConversionExpression
(
s
"""it.get()"""
,
attrType
);
s
"""$unmapped.map{ $conversionFunction }"""
}
else
{
unmapped
}
generateAndPrependExpr
(
e
,
inSelect
,
expr
)
}
def
translateList
(
exprs
:
List
[
Expressions.Expression
],
isAnonymousTraveral
:
Boolean
,
inSelect
:
Boolean
)
:
java.util.List
[
GroovyExpression
]
=
{
var
parent
=
if
(
isAnonymousTraveral
)
{
GremlinExpressionFactory
.
INSTANCE
.
getAnonymousTraversalExpression
()
}
else
{
null
}
var
result
:
java.util.List
[
GroovyExpression
]
=
new
java
.
util
.
ArrayList
(
exprs
.
size
);
exprs
.
foreach
{
it
=>
result
.
add
(
genQuery
(
parent
,
it
,
inSelect
));
}
return
result
;
}
def
generateAndPrependExpr
(
e1
:
Option
[
Expression
],
inSelect
:
Boolean
,
e2
:
String
)
:
String
=
e1
match
{
def
translateOptChild
(
parent
:
GroovyExpression
,
child
:
Option
[
Expressions.Expression
]
,
inSelect
:
Boolean
)
:
GroovyExpression
=
child
match
{
case
Some
(
x
)
=>
s
"""${genQuery(x, inSelect)}.$e2"""
case
None
=>
e2
case
Some
(
x
)
=>
genQuery
(
parent
,
x
,
inSelect
)
case
None
=>
parent
}
def
genHasPredicate
(
e
:
Option
[
Expression
],
fInfo
:
FieldInfo
,
fieldName
:
String
,
inSelect
:
Boolean
,
c
:
ComparisonExpression
,
expr
:
Expression
)
:
String
=
{
def
translateLiteralValue
(
dataType
:
IDataType
[
_
],
l
:
Literal
[
_
])
:
GroovyExpression
=
{
val
qualifiedPropertyName
=
s
"${gPersistenceBehavior.fieldNameInVertex(fInfo.dataType, fInfo.attrInfo)}"
val
persistentExprValue
=
translateValueToPersistentForm
(
fInfo
,
expr
);
if
(
gPersistenceBehavior
.
getSupportedGremlinVersion
()
==
GremlinVersion
.
TWO
)
{
return
generateAndPrependExpr
(
e
,
inSelect
,
s
"""has("${qualifiedPropertyName}", ${gPersistenceBehavior.gremlinCompOp(c)}, $persistentExprValue)"""
);
if
(
dataType
==
DataTypes
.
DATE_TYPE
)
{
try
{
//Accepts both date, datetime formats
val
dateStr
=
cleanStringLiteral
(
l
)
val
dateVal
=
ISODateTimeFormat
.
dateOptionalTimeParser
().
parseDateTime
(
dateStr
).
getMillis
return
new
LiteralExpression
(
dateVal
)
}
catch
{
case
pe
:
java.text.ParseException
=>
throw
new
GremlinTranslationException
(
l
,
"Date format "
+
l
+
" not supported. Should be of the format "
+
TypeSystem
.
getInstance
().
getDateFormat
.
toPattern
);
}
}
else
if
(
dataType
==
DataTypes
.
BYTE_TYPE
)
{
//cast needed, otherwise get class cast exception when trying to compare, since the
//persist value is assumed to be an Integer
return
new
CastExpression
(
new
LiteralExpression
(
Byte
.
valueOf
(
s
"""${l}"""
),
true
),
"byte"
);
}
else
if
(
dataType
==
DataTypes
.
INT_TYPE
)
{
return
new
LiteralExpression
(
Integer
.
valueOf
(
s
"""${l}"""
));
}
else
if
(
dataType
==
DataTypes
.
BOOLEAN_TYPE
)
{
return
new
LiteralExpression
(
Boolean
.
valueOf
(
s
"""${l}"""
));
}
else
if
(
dataType
==
DataTypes
.
SHORT_TYPE
)
{
return
new
CastExpression
(
new
LiteralExpression
(
Short
.
valueOf
(
s
"""${l}"""
),
true
),
"short"
);
}
else
if
(
dataType
==
DataTypes
.
LONG_TYPE
)
{
return
new
LiteralExpression
(
Long
.
valueOf
(
s
"""${l}"""
),
true
);
}
else
if
(
dataType
==
DataTypes
.
FLOAT_TYPE
)
{
return
new
LiteralExpression
(
Float
.
valueOf
(
s
"""${l}"""
),
true
);
}
else
if
(
dataType
==
DataTypes
.
DOUBLE_TYPE
)
{
return
new
LiteralExpression
(
Double
.
valueOf
(
s
"""${l}"""
),
true
);
}
else
if
(
dataType
==
DataTypes
.
STRING_TYPE
)
{
return
new
LiteralExpression
(
cleanStringLiteral
(
l
));
}
else
{
val
attrInfo
:
AttributeInfo
=
fInfo
.
attrInfo
;
val
attrType
:
IDataType
[
_
]
=
attrInfo
.
dataType
;
if
(
gPersistenceBehavior
.
isPropertyValueConversionNeeded
(
attrType
))
{
//for some types, the logical value cannot be stored directly in the underlying graph,
//and conversion logic is needed to convert the persistent form of the value
//to the actual value. In cases like this, we generate a conversion expression to
//do this conversion and use the filter step to perform the comparsion in the gremlin query
val
vertexExpr
=
"((Vertex)it.get())"
;
val
conversionExpr
=
gPersistenceBehavior
.
generatePersisentToLogicalConversionExpression
(
s
"""$vertexExpr.value("$qualifiedPropertyName")"""
,
attrType
);
return
generateAndPrependExpr
(
e
,
inSelect
,
s
"""filter{$vertexExpr.property("$qualifiedPropertyName").isPresent() && $conversionExpr ${gPersistenceBehavior.gremlinPrimitiveOp(c)} $persistentExprValue}"""
);
}
else
{
return
generateAndPrependExpr
(
e
,
inSelect
,
s
"""has("${qualifiedPropertyName}", ${gPersistenceBehavior.gremlinCompOp(c)}($persistentExprValue))"""
);
}
}
return
new
LiteralExpression
(
l
.
rawValue
);
}
}
def
translateValueToPersistentForm
(
fInfo
:
FieldInfo
,
l
:
Expression
)
:
Any
=
{
val
dataType
=
fInfo
.
attrInfo
.
dataType
;
val
QUOTE
=
"\""
;
if
(
dataType
==
DataTypes
.
DATE_TYPE
)
{
try
{
//Accepts both date, datetime formats
val
dateStr
=
l
.
toString
.
stripPrefix
(
QUOTE
).
stripSuffix
(
QUOTE
)
val
dateVal
=
ISODateTimeFormat
.
dateOptionalTimeParser
().
parseDateTime
(
dateStr
).
getMillis
return
dateVal
}
catch
{
case
pe
:
java.text.ParseException
=>
throw
new
GremlinTranslationException
(
l
,
"Date format "
+
l
+
" not supported. Should be of the format "
+
TypeSystem
.
getInstance
().
getDateFormat
.
toPattern
);
}
}
else
if
(
dataType
==
DataTypes
.
BYTE_TYPE
)
{
//cast needed, otherwise get class cast exception when trying to compare, since the
//persist value is assumed to be an Integer
return
s
"""(byte)$l"""
}
else
if
(
dataType
==
DataTypes
.
SHORT_TYPE
)
{
return
s
"""(short)$l"""
}
else
if
(
dataType
==
DataTypes
.
LONG_TYPE
)
{
return
s
"""${l}L"""
}
else
if
(
dataType
==
DataTypes
.
FLOAT_TYPE
)
{
return
s
"""${l}f"""
}
else
if
(
dataType
==
DataTypes
.
DOUBLE_TYPE
)
{
return
s
"""${l}d"""
}
else
if
(
dataType
==
DataTypes
.
STRING_TYPE
)
{
return
string
(
escape
(
l
.
toString
.
stripPrefix
(
QUOTE
).
stripSuffix
(
QUOTE
)));
}
else
{
return
l
}
}
def
genFullQuery
(
expr
:
Expression
,
hasSelect
:
Boolean
)
:
String
=
{
var
q
=
genQuery
(
expr
,
false
)
var
q
:
GroovyExpression
=
new
FunctionCallExpression
(
new
IdentifierExpression
(
"g"
),
"V"
);
val
debug
:
Boolean
=
false
if
(
gPersistenceBehavior
.
addGraphVertexPrefix
(
preStatements
))
{
q
=
s
"g.V()${gPersistenceBehavior.initialQueryCondition}.$q"
q
=
gPersistenceBehavior
.
addInitialQueryCondition
(
q
);
}
q
=
s
"$q.toList()${gPersistenceBehavior.getGraph().getOutputTransformationPredicate(hasSelect, expr.isInstanceOf[PathExpression])}"
q
=
genQuery
(
q
,
expr
,
false
)
q
=
new
FunctionCallExpression
(
q
,
"toList"
);
q
=
gPersistenceBehavior
.
getGraph
().
addOutputTransformationPredicate
(
q
,
hasSelect
,
expr
.
isInstanceOf
[
PathExpression
]);
var
overallExpression
=
new
CodeBlockExpression
();
overallExpression
.
addStatements
(
preStatements
);
overallExpression
.
addStatement
(
q
)
overallExpression
.
addStatements
(
postStatements
);
var
qryStr
=
generateGremlin
(
overallExpression
);
if
(
debug
)
{
println
(
" query "
+
q
)
println
(
" query "
+
q
ryStr
)
}
q
=
(
preStatements
++
Seq
(
q
)
++
postStatements
).
mkString
(
""
,
";"
,
""
)
/*
* the L:{} represents a groovy code block; the label is needed
* to distinguish it from a groovy closure.
*/
s
"L:{$q}"
qryStr
;
}
def
generateGremlin
(
expr
:
GroovyExpression
)
:
String
=
{
val
ctx
:
GroovyGenerationContext
=
new
GroovyGenerationContext
();
ctx
.
setParametersAllowed
(
false
);
expr
.
generateGroovy
(
ctx
);
return
ctx
.
getQuery
;
}
def
translate
()
:
GremlinQuery
=
{
var
e1
=
expr
.
transformUp
(
wrapAndRule
)
...
...
@@ -570,9 +537,9 @@ class GremlinTranslator(expr: Expression,
e1
=
e1
.
transformUp
(
addAliasToLoopInput
())
e1
=
e1
.
transformUp
(
instanceClauseToTop
(
e1
))
e1
=
e1
.
transformUp
(
traitClauseWithInstanceForTop
(
e1
))
//Following code extracts the select expressions from expression tree.
val
se
=
SelectExpressionHelper
.
extractSelectExpression
(
e1
)
if
(
se
.
isDefined
)
{
val
rMap
=
buildResultMapping
(
se
.
get
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment