http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1GraphManagement.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1GraphManagement.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1GraphManagement.java new file mode 100644 index 0000000..12faeda --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1GraphManagement.java @@ -0,0 +1,177 @@ +/** + * 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.repository.graphdb.titan1; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.atlas.repository.graphdb.AtlasCardinality; +import org.apache.atlas.repository.graphdb.AtlasGraphIndex; +import org.apache.atlas.repository.graphdb.AtlasGraphManagement; +import org.apache.atlas.repository.graphdb.AtlasPropertyKey; +import org.apache.commons.lang.StringUtils; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Element; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.thinkaurelius.titan.core.Cardinality; +import com.thinkaurelius.titan.core.PropertyKey; +import com.thinkaurelius.titan.core.schema.Mapping; +import com.thinkaurelius.titan.core.schema.PropertyKeyMaker; +import com.thinkaurelius.titan.core.schema.TitanGraphIndex; +import com.thinkaurelius.titan.core.schema.TitanManagement; +import com.thinkaurelius.titan.graphdb.internal.Token; + +/** + * Titan 1.0.0 implementation of AtlasGraphManagement. + */ +public class Titan1GraphManagement implements AtlasGraphManagement { + + private static final Logger LOG = LoggerFactory.getLogger(Titan1GraphManagement.class); + + private static final char[] RESERVED_CHARS = { '{', '}', '"', '$', Token.SEPARATOR_CHAR }; + + private Titan1Graph graph; + private TitanManagement management; + + private Set<String> newMultProperties = new HashSet<>(); + + public Titan1GraphManagement(Titan1Graph graph, TitanManagement managementSystem) { + this.management = managementSystem; + this.graph = graph; + } + + @Override + public void createVertexIndex(String propertyName, String backingIndex, List<AtlasPropertyKey> propertyKeys) { + + TitanManagement.IndexBuilder indexBuilder = management.buildIndex(propertyName, Vertex.class); + for (AtlasPropertyKey key : propertyKeys) { + PropertyKey titanKey = TitanObjectFactory.createPropertyKey(key); + indexBuilder.addKey(titanKey); + } + indexBuilder.buildMixedIndex(backingIndex); + } + + @Override + public void createEdgeIndex(String index, String backingIndex) { + buildMixedIndex(index, Edge.class, backingIndex); + } + + private void buildMixedIndex(String index, Class<? extends Element> titanClass, String backingIndex) { + + management.buildIndex(index, titanClass).buildMixedIndex(backingIndex); + } + + @Override + public void createFullTextIndex(String indexName, AtlasPropertyKey propertyKey, String backingIndex) { + + PropertyKey fullText = TitanObjectFactory.createPropertyKey(propertyKey); + + management.buildIndex(indexName, Vertex.class) + .addKey(fullText, com.thinkaurelius.titan.core.schema.Parameter.of("mapping", Mapping.TEXT)) + .buildMixedIndex(backingIndex); + } + + @Override + public boolean containsPropertyKey(String propertyName) { + return management.containsPropertyKey(propertyName); + } + + @Override + public void rollback() { + management.rollback(); + + } + + @Override + public void commit() { + graph.addMultiProperties(newMultProperties); + newMultProperties.clear(); + management.commit(); + } + + private static void checkName(String name) { + //for some reason, name checking was removed from StandardPropertyKeyMaker.make() + //in titan 1. For consistency, do the check here. + Preconditions.checkArgument(StringUtils.isNotBlank(name), "Need to specify name"); + for (char c : RESERVED_CHARS) { + Preconditions.checkArgument(name.indexOf(c) < 0, "Name can not contains reserved character %s: %s", c, + name); + } + + } + + @Override + public AtlasPropertyKey makePropertyKey(String propertyName, Class propertyClass, AtlasCardinality cardinality) { + + if (cardinality.isMany()) { + newMultProperties.add(propertyName); + } + PropertyKeyMaker propertyKeyBuilder = management.makePropertyKey(propertyName).dataType(propertyClass); + if (cardinality != null) { + Cardinality titanCardinality = TitanObjectFactory.createCardinality(cardinality); + propertyKeyBuilder.cardinality(titanCardinality); + } + PropertyKey propertyKey = propertyKeyBuilder.make(); + return GraphDbObjectFactory.createPropertyKey(propertyKey); + } + + @Override + public AtlasPropertyKey getPropertyKey(String propertyName) { + checkName(propertyName); + return GraphDbObjectFactory.createPropertyKey(management.getPropertyKey(propertyName)); + } + + public void createExactMatchVertexIndex(String propertyName, boolean enforceUniqueness, + List<AtlasPropertyKey> propertyKeys) { + + TitanManagement.IndexBuilder indexBuilder = management.buildIndex(propertyName, Vertex.class); + for (AtlasPropertyKey key : propertyKeys) { + PropertyKey titanKey = TitanObjectFactory.createPropertyKey(key); + indexBuilder.addKey(titanKey); + } + if (enforceUniqueness) { + indexBuilder.unique(); + } + indexBuilder.buildCompositeIndex(); + } + + @Override + public void addVertexIndexKey(String indexName, AtlasPropertyKey propertyKey) { + PropertyKey titanKey = TitanObjectFactory.createPropertyKey(propertyKey); + TitanGraphIndex vertexIndex = management.getGraphIndex(indexName); + management.addIndexKey(vertexIndex, titanKey); + } + + @Override + public AtlasGraphIndex getGraphIndex(String indexName) { + TitanGraphIndex index = management.getGraphIndex(indexName); + return GraphDbObjectFactory.createGraphIndex(index); + } + + @Override + public void createExactMatchIndex(String propertyName, boolean isUnique, + List<AtlasPropertyKey> propertyKeys) { + createExactMatchVertexIndex(propertyName, isUnique, propertyKeys); + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1IndexQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1IndexQuery.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1IndexQuery.java new file mode 100644 index 0000000..4073dd2 --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1IndexQuery.java @@ -0,0 +1,79 @@ +/** + * 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.repository.graphdb.titan1; + +import java.util.Iterator; + +import org.apache.atlas.repository.graphdb.AtlasIndexQuery; +import org.apache.atlas.repository.graphdb.AtlasVertex; + +import com.google.common.base.Function; +import com.google.common.collect.Iterators; +import com.thinkaurelius.titan.core.TitanIndexQuery; +import com.thinkaurelius.titan.core.TitanVertex; + +/** + * Titan 1.0.0 implementation of AtlasIndexQuery. + */ +public class Titan1IndexQuery implements AtlasIndexQuery<Titan1Vertex, Titan1Edge> { + + private Titan1Graph graph; + private TitanIndexQuery query; + + public Titan1IndexQuery(Titan1Graph graph, TitanIndexQuery query) { + this.query = query; + this.graph = graph; + } + + @Override + public Iterator<Result<Titan1Vertex, Titan1Edge>> vertices() { + Iterator<TitanIndexQuery.Result<TitanVertex>> results = query.vertices().iterator(); + + Function<TitanIndexQuery.Result<TitanVertex>, Result<Titan1Vertex, Titan1Edge>> function = + new Function<TitanIndexQuery.Result<TitanVertex>, Result<Titan1Vertex, Titan1Edge>>() { + + @Override + public Result<Titan1Vertex, Titan1Edge> apply(TitanIndexQuery.Result<TitanVertex> source) { + return new ResultImpl(source); + } + }; + + return Iterators.transform(results, function); + } + + /** + * Titan 1.0.0 implementation of AtlasIndexQuery.Result. + */ + public final class ResultImpl implements AtlasIndexQuery.Result<Titan1Vertex, Titan1Edge> { + private TitanIndexQuery.Result<TitanVertex> source; + + public ResultImpl(TitanIndexQuery.Result<TitanVertex> source) { + this.source = source; + } + + @Override + public AtlasVertex<Titan1Vertex, Titan1Edge> getVertex() { + return GraphDbObjectFactory.createVertex(graph, source.getElement()); + } + + @Override + public double getScore() { + return source.getScore(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1PropertyKey.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1PropertyKey.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1PropertyKey.java new file mode 100644 index 0000000..6b62f27 --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1PropertyKey.java @@ -0,0 +1,77 @@ +/** + * 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.repository.graphdb.titan1; + +import org.apache.atlas.repository.graphdb.AtlasCardinality; +import org.apache.atlas.repository.graphdb.AtlasPropertyKey; + +import com.thinkaurelius.titan.core.PropertyKey; + +/** + * + */ +public class Titan1PropertyKey implements AtlasPropertyKey { + + private PropertyKey wrapped; + + public Titan1PropertyKey(PropertyKey toWrap) { + wrapped = toWrap; + } + + /* (non-Javadoc) + * @see org.apache.atlas.repository.graphdb.AtlasPropertyKey#getName() + */ + @Override + public String getName() { + return wrapped.name(); + } + + /** + * @return + */ + public PropertyKey getWrappedPropertyKey() { + return wrapped; + } + + @Override + public int hashCode() { + int result = 17; + result = 37*result + wrapped.hashCode(); + return result; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof Titan1PropertyKey)) { + return false; + } + Titan1PropertyKey otherKey = (Titan1PropertyKey)other; + return otherKey.getWrappedPropertyKey().equals(getWrappedPropertyKey()); + + } + + /* (non-Javadoc) + * @see org.apache.atlas.repository.graphdb.AtlasPropertyKey#getCardinality() + */ + @Override + public AtlasCardinality getCardinality() { + return GraphDbObjectFactory.createCardinality(wrapped.cardinality()); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1Vertex.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1Vertex.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1Vertex.java new file mode 100644 index 0000000..1670e92 --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1Vertex.java @@ -0,0 +1,102 @@ +/** + * 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.repository.graphdb.titan1; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +import org.apache.atlas.repository.graphdb.AtlasEdge; +import org.apache.atlas.repository.graphdb.AtlasEdgeDirection; +import org.apache.atlas.repository.graphdb.AtlasSchemaViolationException; +import org.apache.atlas.repository.graphdb.AtlasVertex; +import org.apache.atlas.repository.graphdb.AtlasVertexQuery; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; + +import com.thinkaurelius.titan.core.SchemaViolationException; +import com.thinkaurelius.titan.core.TitanVertex; +/** + * Titan 1.0.0 implementation of AtlasVertex. + */ +public class Titan1Vertex extends Titan1Element<Vertex> implements AtlasVertex<Titan1Vertex, Titan1Edge> { + + + public Titan1Vertex(Titan1Graph graph, Vertex source) { + super(graph, source); + } + + @Override + public <T> void addProperty(String propertyName, T value) { + try { + getWrappedElement().property(VertexProperty.Cardinality.set, propertyName, value); + } catch(SchemaViolationException e) { + throw new AtlasSchemaViolationException(e); + } + } + + + + @Override + public Iterable<AtlasEdge<Titan1Vertex, Titan1Edge>> getEdges(AtlasEdgeDirection dir, String edgeLabel) { + + Direction d = TitanObjectFactory.createDirection(dir); + Iterator<Edge> edges = getWrappedElement().edges(d, edgeLabel); + return graph.wrapEdges(edges); + } + + private TitanVertex getAsTitanVertex() { + return (TitanVertex)getWrappedElement(); + } + + @Override + public Iterable<AtlasEdge<Titan1Vertex, Titan1Edge>> getEdges(AtlasEdgeDirection in) { + Direction d = TitanObjectFactory.createDirection(in); + Iterator<Edge> edges = getWrappedElement().edges(d); + return graph.wrapEdges(edges); + } + + @Override + public <T> Collection<T> getPropertyValues(String propertyName, Class<T> clazz) { + + Collection<T> result = new ArrayList<T>(); + Iterator<VertexProperty<T>> it = getWrappedElement().properties(propertyName); + while(it.hasNext()) { + result.add(it.next().value()); + } + + return result; + } + + @Override + public AtlasVertexQuery<Titan1Vertex, Titan1Edge> query() { + + return new Titan1VertexQuery(graph, getAsTitanVertex().query()); + } + + + @Override + public Titan1Vertex getV() { + return this; + } + + + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1VertexQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1VertexQuery.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1VertexQuery.java new file mode 100644 index 0000000..4452bcd --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/Titan1VertexQuery.java @@ -0,0 +1,66 @@ +/** + * 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.repository.graphdb.titan1; + +import org.apache.atlas.repository.graphdb.AtlasEdge; +import org.apache.atlas.repository.graphdb.AtlasEdgeDirection; +import org.apache.atlas.repository.graphdb.AtlasVertex; +import org.apache.atlas.repository.graphdb.AtlasVertexQuery; + +import com.thinkaurelius.titan.core.TitanVertexQuery; + +/** + * Titan 1.0.0 implementation of AtlasVertexQuery. + */ +public class Titan1VertexQuery implements AtlasVertexQuery<Titan1Vertex, Titan1Edge> { + + private Titan1Graph graph; + private TitanVertexQuery<?> query; + + public Titan1VertexQuery(Titan1Graph graph, TitanVertexQuery<?> query) { + this.query = query; + this.graph = graph; + } + + @Override + public AtlasVertexQuery<Titan1Vertex, Titan1Edge> direction(AtlasEdgeDirection queryDirection) { + query.direction(TitanObjectFactory.createDirection(queryDirection)); + return this; + + } + + @Override + public Iterable<AtlasVertex<Titan1Vertex, Titan1Edge>> vertices() { + Iterable vertices = query.vertices(); + return graph.wrapVertices(vertices); + } + + @Override + public Iterable<AtlasEdge<Titan1Vertex, Titan1Edge>> edges() { + Iterable edges = query.edges(); + return graph.wrapEdges(edges); + + } + + @Override + public long count() { + return query.count(); + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/TitanObjectFactory.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/TitanObjectFactory.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/TitanObjectFactory.java new file mode 100644 index 0000000..a4776a9 --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/TitanObjectFactory.java @@ -0,0 +1,85 @@ +/** + * 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.repository.graphdb.titan1; + +import org.apache.atlas.repository.graphdb.AtlasCardinality; +import org.apache.atlas.repository.graphdb.AtlasEdgeDirection; +import org.apache.atlas.repository.graphdb.AtlasPropertyKey; +import org.apache.tinkerpop.gremlin.structure.Direction; + +import com.thinkaurelius.titan.core.Cardinality; +import com.thinkaurelius.titan.core.PropertyKey; + + +/** + * Factory that serves up instances of Titan/Tinkerpop classes that correspond to + * graph database abstraction layer/Atlas classes. + */ +public final class TitanObjectFactory { + + private TitanObjectFactory() { + + } + + /** + * Retrieves the titan direction corresponding to the given + * AtlasEdgeDirection. + * + * @param dir + * @return + */ + public static Direction createDirection(AtlasEdgeDirection dir) { + + switch(dir) { + case IN: + return Direction.IN; + case OUT: + return Direction.OUT; + case BOTH: + return Direction.BOTH; + default: + throw new RuntimeException("Unrecognized direction: " + dir); + } + } + + + /** + * Converts a Multiplicity to a Cardinality. + * + * @param multiplicity + * @return + */ + public static Cardinality createCardinality(AtlasCardinality cardinality) { + switch(cardinality) { + + case SINGLE: + return Cardinality.SINGLE; + case LIST: + return Cardinality.LIST; + case SET: + return Cardinality.SET; + default: + throw new IllegalStateException("Unrecognized cardinality: " + cardinality); + } + } + + public static PropertyKey createPropertyKey(AtlasPropertyKey key) { + return ((Titan1PropertyKey)key).getWrappedPropertyKey(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasElementPropertyConfig.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasElementPropertyConfig.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasElementPropertyConfig.java new file mode 100644 index 0000000..df67a83 --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasElementPropertyConfig.java @@ -0,0 +1,136 @@ +/** + * 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.repository.graphdb.titan1.graphson; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * Configure how the GraphSON utility treats edge and vertex properties. + * + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class AtlasElementPropertyConfig { + + /** + * Rules for element properties. + */ + public enum ElementPropertiesRule { + INCLUDE, EXCLUDE + } + + private final List<String> vertexPropertyKeys; + private final List<String> edgePropertyKeys; + private final ElementPropertiesRule vertexPropertiesRule; + private final ElementPropertiesRule edgePropertiesRule; + private final boolean normalized; + + /** + * A configuration that includes all properties of vertices and edges. + */ + public static final AtlasElementPropertyConfig ALL_PROPERTIES = new AtlasElementPropertyConfig(null, null, + ElementPropertiesRule.INCLUDE, ElementPropertiesRule.INCLUDE, false); + + public AtlasElementPropertyConfig(final Set<String> vertexPropertyKeys, final Set<String> edgePropertyKeys, + final ElementPropertiesRule vertexPropertiesRule, final ElementPropertiesRule edgePropertiesRule) { + this(vertexPropertyKeys, edgePropertyKeys, vertexPropertiesRule, edgePropertiesRule, false); + } + + public AtlasElementPropertyConfig(final Set<String> vertexPropertyKeys, final Set<String> edgePropertyKeys, + final ElementPropertiesRule vertexPropertiesRule, final ElementPropertiesRule edgePropertiesRule, + final boolean normalized) { + this.vertexPropertiesRule = vertexPropertiesRule; + this.vertexPropertyKeys = sortKeys(vertexPropertyKeys, normalized); + this.edgePropertiesRule = edgePropertiesRule; + this.edgePropertyKeys = sortKeys(edgePropertyKeys, normalized); + this.normalized = normalized; + } + + /** + * Construct a configuration that includes the specified properties from + * both vertices and edges. + */ + public static AtlasElementPropertyConfig includeProperties(final Set<String> vertexPropertyKeys, + final Set<String> edgePropertyKeys) { + return new AtlasElementPropertyConfig(vertexPropertyKeys, edgePropertyKeys, ElementPropertiesRule.INCLUDE, + ElementPropertiesRule.INCLUDE); + } + + public static AtlasElementPropertyConfig includeProperties(final Set<String> vertexPropertyKeys, + final Set<String> edgePropertyKeys, + final boolean normalized) { + return new AtlasElementPropertyConfig(vertexPropertyKeys, edgePropertyKeys, ElementPropertiesRule.INCLUDE, + ElementPropertiesRule.INCLUDE, normalized); + } + + /** + * Construct a configuration that excludes the specified properties from + * both vertices and edges. + */ + public static AtlasElementPropertyConfig excludeProperties(final Set<String> vertexPropertyKeys, + final Set<String> edgePropertyKeys) { + return new AtlasElementPropertyConfig(vertexPropertyKeys, edgePropertyKeys, ElementPropertiesRule.EXCLUDE, + ElementPropertiesRule.EXCLUDE); + } + + public static AtlasElementPropertyConfig excludeProperties(final Set<String> vertexPropertyKeys, + final Set<String> edgePropertyKeys, + final boolean normalized) { + return new AtlasElementPropertyConfig(vertexPropertyKeys, edgePropertyKeys, ElementPropertiesRule.EXCLUDE, + ElementPropertiesRule.EXCLUDE, normalized); + } + + public List<String> getVertexPropertyKeys() { + return vertexPropertyKeys; + } + + public List<String> getEdgePropertyKeys() { + return edgePropertyKeys; + } + + public ElementPropertiesRule getVertexPropertiesRule() { + return vertexPropertiesRule; + } + + public ElementPropertiesRule getEdgePropertiesRule() { + return edgePropertiesRule; + } + + public boolean isNormalized() { + return normalized; + } + + private static List<String> sortKeys(final Set<String> keys, final boolean normalized) { + final List<String> propertyKeyList; + if (keys != null) { + if (normalized) { + final List<String> sorted = new ArrayList<String>(keys); + Collections.sort(sorted); + propertyKeyList = sorted; + } else { + propertyKeyList = new ArrayList<String>(keys); + } + } else { + propertyKeyList = null; + } + + return propertyKeyList; + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONMode.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONMode.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONMode.java new file mode 100644 index 0000000..2bab287 --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONMode.java @@ -0,0 +1,43 @@ +/** + * 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.repository.graphdb.titan1.graphson; + +/** + * Modes of operation of the GraphSONUtility. + * + * @author Stephen Mallette + */ +public enum AtlasGraphSONMode { + /** + * COMPACT constructs GraphSON on the assumption that all property keys + * are fair game for exclusion including _type, _inV, _outV, _label and _id. + * It is possible to write GraphSON that cannot be read back into Graph, + * if some or all of these keys are excluded. + */ + COMPACT, + + /** + * NORMAL includes the _type field and JSON data typing. + */ + NORMAL, + + /** + * EXTENDED includes the _type field and explicit data typing. + */ + EXTENDED +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONTokens.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONTokens.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONTokens.java new file mode 100644 index 0000000..49bbdb4 --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONTokens.java @@ -0,0 +1,51 @@ +/** + * 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.repository.graphdb.titan1.graphson; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public final class AtlasGraphSONTokens { + + private AtlasGraphSONTokens() {} + + public static final String VERTEX = "vertex"; + public static final String EDGE = "edge"; + public static final String INTERNAL_ID = "_id"; + public static final String INTERNAL_LABEL = "_label"; + public static final String INTERNAL_TYPE = "_type"; + public static final String INTERNAL_OUT_V = "_outV"; + public static final String INTERNAL_IN_V = "_inV"; + public static final String VALUE = "value"; + public static final String TYPE = "type"; + public static final String TYPE_LIST = "list"; + public static final String TYPE_STRING = "string"; + public static final String TYPE_DOUBLE = "double"; + public static final String TYPE_INTEGER = "integer"; + public static final String TYPE_FLOAT = "float"; + public static final String TYPE_MAP = "map"; + public static final String TYPE_BOOLEAN = "boolean"; + public static final String TYPE_LONG = "long"; + public static final String TYPE_SHORT = "short"; + public static final String TYPE_BYTE = "byte"; + public static final String TYPE_UNKNOWN = "unknown"; + + public static final String VERTICES = "vertices"; + public static final String EDGES = "edges"; + public static final String MODE = "mode"; +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONUtility.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONUtility.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONUtility.java new file mode 100644 index 0000000..26abe2e --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/graphson/AtlasGraphSONUtility.java @@ -0,0 +1,513 @@ +/** + * 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.repository.graphdb.titan1.graphson; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.atlas.repository.graphdb.AtlasEdge; +import org.apache.atlas.repository.graphdb.AtlasElement; +import org.apache.atlas.repository.graphdb.AtlasVertex; +import org.apache.atlas.repository.graphdb.titan1.graphson.AtlasElementPropertyConfig.ElementPropertiesRule; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.codehaus.jettison.json.JSONTokener; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * This class was largely removed from tinkerpop 1. We're adding it back here to + * avoid changing the format of the JSON that we produce. + * + * Helps write individual graph elements to TinkerPop JSON format known as + * GraphSON. + * + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public final class AtlasGraphSONUtility { + + private static final JsonNodeFactory JSON_NODE_FACTORY = JsonNodeFactory.instance; + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private final AtlasGraphSONMode mode; + private final List<String> vertexPropertyKeys; + private final List<String> edgePropertyKeys; + + private final ElementPropertiesRule vertexPropertiesRule; + private final ElementPropertiesRule edgePropertiesRule; + private final boolean normalized; + + private final boolean includeReservedVertexId; + private final boolean includeReservedEdgeId; + private final boolean includeReservedVertexType; + private final boolean includeReservedEdgeType; + private final boolean includeReservedEdgeLabel; + private final boolean includeReservedEdgeOutV; + private final boolean includeReservedEdgeInV; + + /** + * A GraphSONUtility that includes the specified properties. + */ + private AtlasGraphSONUtility(final AtlasGraphSONMode mode, final Set<String> vertexPropertyKeySet, + final Set<String> edgePropertyKeySet) { + + AtlasElementPropertyConfig config = AtlasElementPropertyConfig.includeProperties(vertexPropertyKeySet, + edgePropertyKeySet); + + this.vertexPropertyKeys = config.getVertexPropertyKeys(); + this.edgePropertyKeys = config.getEdgePropertyKeys(); + this.vertexPropertiesRule = config.getVertexPropertiesRule(); + this.edgePropertiesRule = config.getEdgePropertiesRule(); + this.normalized = config.isNormalized(); + + this.mode = mode; + + this.includeReservedVertexId = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_ID, vertexPropertyKeys, + this.vertexPropertiesRule); + this.includeReservedEdgeId = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_ID, edgePropertyKeys, + this.edgePropertiesRule); + this.includeReservedVertexType = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_TYPE, vertexPropertyKeys, + this.vertexPropertiesRule); + this.includeReservedEdgeType = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_TYPE, edgePropertyKeys, + this.edgePropertiesRule); + this.includeReservedEdgeLabel = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_LABEL, edgePropertyKeys, + this.edgePropertiesRule); + this.includeReservedEdgeOutV = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_OUT_V, edgePropertyKeys, + this.edgePropertiesRule); + this.includeReservedEdgeInV = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_IN_V, edgePropertyKeys, + this.edgePropertiesRule); + } + + /* + * Creates GraphSON for a single graph element. + */ + private JSONObject jsonFromElement(final AtlasElement element) throws JSONException { + final ObjectNode objectNode = this.objectNodeFromElement(element); + + try { + return new JSONObject(new JSONTokener(MAPPER.writeValueAsString(objectNode))); + } catch (IOException ioe) { + // repackage this as a JSONException...seems sensible as the caller will only know about + // the jettison object not being created + throw new JSONException(ioe); + } + } + + /** + * Creates GraphSON for a single graph element. + */ + private ObjectNode objectNodeFromElement(final AtlasElement element) { + final boolean isEdge = element instanceof AtlasEdge; + final boolean showTypes = mode == AtlasGraphSONMode.EXTENDED; + final List<String> propertyKeys = isEdge ? this.edgePropertyKeys : this.vertexPropertyKeys; + final ElementPropertiesRule elementPropertyConfig = isEdge ? this.edgePropertiesRule + : this.vertexPropertiesRule; + + final ObjectNode jsonElement = createJSONMap( + createPropertyMap(element, propertyKeys, elementPropertyConfig, normalized), propertyKeys, showTypes); + + if ((isEdge && this.includeReservedEdgeId) || (!isEdge && this.includeReservedVertexId)) { + putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_ID, element.getId()); + } + + // it's important to keep the order of these straight. check AtlasEdge first and then AtlasVertex because there + // are graph implementations that have AtlasEdge extend from AtlasVertex + if (element instanceof AtlasEdge) { + final AtlasEdge edge = (AtlasEdge) element; + + if (this.includeReservedEdgeId) { + putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_ID, element.getId()); + } + + if (this.includeReservedEdgeType) { + jsonElement.put(AtlasGraphSONTokens.INTERNAL_TYPE, AtlasGraphSONTokens.EDGE); + } + + if (this.includeReservedEdgeOutV) { + putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_OUT_V, edge.getOutVertex().getId()); + } + + if (this.includeReservedEdgeInV) { + putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_IN_V, edge.getInVertex().getId()); + } + + if (this.includeReservedEdgeLabel) { + jsonElement.put(AtlasGraphSONTokens.INTERNAL_LABEL, edge.getLabel()); + } + } else if (element instanceof AtlasVertex) { + if (this.includeReservedVertexId) { + putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_ID, element.getId()); + } + + if (this.includeReservedVertexType) { + jsonElement.put(AtlasGraphSONTokens.INTERNAL_TYPE, AtlasGraphSONTokens.VERTEX); + } + } + + return jsonElement; + } + + /** + * Creates a Jettison JSONObject from a graph element. + * + * @param element + * the graph element to convert to JSON. + * @param propertyKeys + * The property getPropertyKeys() at the root of the element to + * serialize. If null, then all getPropertyKeys() are serialized. + * @param mode + * the type of GraphSON to be generated. + */ + public static JSONObject jsonFromElement(final AtlasElement element, final Set<String> propertyKeys, + final AtlasGraphSONMode mode) + throws JSONException { + + final AtlasGraphSONUtility graphson = element instanceof AtlasEdge + ? new AtlasGraphSONUtility(mode, null, propertyKeys) + : new AtlasGraphSONUtility(mode, propertyKeys, null); + return graphson.jsonFromElement(element); + } + + private static ObjectNode objectNodeFromElement(final AtlasElement element, final List<String> propertyKeys, + final AtlasGraphSONMode mode) { + final AtlasGraphSONUtility graphson = element instanceof AtlasEdge + ? new AtlasGraphSONUtility(mode, null, new HashSet<String>(propertyKeys)) + : new AtlasGraphSONUtility(mode, new HashSet<String>(propertyKeys), null); + return graphson.objectNodeFromElement(element); + } + + private static boolean includeReservedKey(final AtlasGraphSONMode mode, final String key, + final List<String> propertyKeys, final ElementPropertiesRule rule) { + // the key is always included in modes other than compact. if it is compact, then validate that the + // key is in the property key list + return mode != AtlasGraphSONMode.COMPACT || includeKey(key, propertyKeys, rule); + } + + private static boolean includeKey(final String key, final List<String> propertyKeys, + final ElementPropertiesRule rule) { + if (propertyKeys == null) { + // when null always include the key and shortcut this piece + return true; + } + + // default the key situation. if it's included then it should be explicitly defined in the + // property getPropertyKeys() list to be included or the reverse otherwise + boolean keySituation = rule == ElementPropertiesRule.INCLUDE; + + switch (rule) { + case INCLUDE: + keySituation = propertyKeys.contains(key); + break; + case EXCLUDE: + keySituation = !propertyKeys.contains(key); + break; + default: + throw new RuntimeException("Unhandled rule: " + rule); + } + + return keySituation; + } + + private static ArrayNode createJSONList(final List<Object> list, final List<String> propertyKeys, + final boolean showTypes) { + final ArrayNode jsonList = JSON_NODE_FACTORY.arrayNode(); + for (Object item : list) { + if (item instanceof AtlasElement) { + jsonList.add(objectNodeFromElement((AtlasElement) item, propertyKeys, + showTypes ? AtlasGraphSONMode.EXTENDED : AtlasGraphSONMode.NORMAL)); + } else if (item instanceof List) { + jsonList.add(createJSONList((List<Object>) item, propertyKeys, showTypes)); + } else if (item instanceof Map) { + jsonList.add(createJSONMap((Map<String, Object>) item, propertyKeys, showTypes)); + } else if (item != null && item.getClass().isArray()) { + jsonList.add(createJSONList(convertArrayToList(item), propertyKeys, showTypes)); + } else { + addObject(jsonList, item); + } + } + return jsonList; + } + + private static ObjectNode createJSONMap(final Map<String, Object> map, final List<String> propertyKeys, + final boolean showTypes) { + final ObjectNode jsonMap = JSON_NODE_FACTORY.objectNode(); + for (Object key : map.keySet()) { + Object value = map.get(key); + if (value != null) { + if (value instanceof List) { + value = createJSONList((List<Object>) value, propertyKeys, showTypes); + } else if (value instanceof Map) { + value = createJSONMap((Map<String, Object>) value, propertyKeys, showTypes); + } else if (value instanceof AtlasElement) { + value = objectNodeFromElement((AtlasElement) value, propertyKeys, + showTypes ? AtlasGraphSONMode.EXTENDED : AtlasGraphSONMode.NORMAL); + } else if (value.getClass().isArray()) { + value = createJSONList(convertArrayToList(value), propertyKeys, showTypes); + } + } + + putObject(jsonMap, key.toString(), getValue(value, showTypes)); + } + return jsonMap; + + } + + private static void addObject(final ArrayNode jsonList, final Object value) { + if (value == null) { + jsonList.add((JsonNode) null); + } else if (value.getClass() == Boolean.class) { + jsonList.add((Boolean) value); + } else if (value.getClass() == Long.class) { + jsonList.add((Long) value); + } else if (value.getClass() == Integer.class) { + jsonList.add((Integer) value); + } else if (value.getClass() == Float.class) { + jsonList.add((Float) value); + } else if (value.getClass() == Double.class) { + jsonList.add((Double) value); + } else if (value.getClass() == Byte.class) { + jsonList.add((Byte) value); + } else if (value.getClass() == Short.class) { + jsonList.add((Short) value); + } else if (value.getClass() == String.class) { + jsonList.add((String) value); + } else if (value instanceof ObjectNode) { + jsonList.add((ObjectNode) value); + } else if (value instanceof ArrayNode) { + jsonList.add((ArrayNode) value); + } else { + jsonList.add(value.toString()); + } + } + + private static void putObject(final ObjectNode jsonMap, final String key, final Object value) { + if (value == null) { + jsonMap.put(key, (JsonNode) null); + } else if (value.getClass() == Boolean.class) { + jsonMap.put(key, (Boolean) value); + } else if (value.getClass() == Long.class) { + jsonMap.put(key, (Long) value); + } else if (value.getClass() == Integer.class) { + jsonMap.put(key, (Integer) value); + } else if (value.getClass() == Float.class) { + jsonMap.put(key, (Float) value); + } else if (value.getClass() == Double.class) { + jsonMap.put(key, (Double) value); + } else if (value.getClass() == Short.class) { + jsonMap.put(key, (Short) value); + } else if (value.getClass() == Byte.class) { + jsonMap.put(key, (Byte) value); + } else if (value.getClass() == String.class) { + jsonMap.put(key, (String) value); + } else if (value instanceof ObjectNode) { + jsonMap.put(key, (ObjectNode) value); + } else if (value instanceof ArrayNode) { + jsonMap.put(key, (ArrayNode) value); + } else { + jsonMap.put(key, value.toString()); + } + } + + private static Map<String, Object> createPropertyMap(final AtlasElement element, final List<String> propertyKeys, + final ElementPropertiesRule rule, final boolean normalized) { + final Map<String, Object> map = new HashMap<String, Object>(); + final List<String> propertyKeyList; + if (normalized) { + final List<String> sorted = new ArrayList<String>(element.getPropertyKeys()); + Collections.sort(sorted); + propertyKeyList = sorted; + } else { + propertyKeyList = new ArrayList<String>(element.getPropertyKeys()); + } + + if (propertyKeys == null) { + for (String key : propertyKeyList) { + final Object valToPutInMap = element.getProperty(key, Object.class); + if (valToPutInMap != null) { + map.put(key, valToPutInMap); + } + } + } else { + if (rule == ElementPropertiesRule.INCLUDE) { + for (String key : propertyKeys) { + final Object valToPutInMap = element.getProperty(key, Object.class); + if (valToPutInMap != null) { + map.put(key, valToPutInMap); + } + } + } else { + for (String key : propertyKeyList) { + if (!propertyKeys.contains(key)) { + final Object valToPutInMap = element.getProperty(key, Object.class); + if (valToPutInMap != null) { + map.put(key, valToPutInMap); + } + } + } + } + } + + return map; + } + + private static Object getValue(Object value, final boolean includeType) { + + Object returnValue = value; + + // if the includeType is set to true then show the data types of the properties + if (includeType) { + + // type will be one of: map, list, string, long, int, double, float. + // in the event of a complex object it will call a toString and store as a + // string + String type = determineType(value); + + ObjectNode valueAndType = JSON_NODE_FACTORY.objectNode(); + valueAndType.put(AtlasGraphSONTokens.TYPE, type); + + if (type.equals(AtlasGraphSONTokens.TYPE_LIST)) { + + // values of lists must be accumulated as ObjectNode objects under the value key. + // will return as a ArrayNode. called recursively to traverse the entire + // object graph of each item in the array. + ArrayNode list = (ArrayNode) value; + + // there is a set of values that must be accumulated as an array under a key + ArrayNode valueArray = valueAndType.putArray(AtlasGraphSONTokens.VALUE); + for (int ix = 0; ix < list.size(); ix++) { + // the value of each item in the array is a node object from an ArrayNode...must + // get the value of it. + addObject(valueArray, getValue(getTypedValueFromJsonNode(list.get(ix)), includeType)); + } + + } else if (type.equals(AtlasGraphSONTokens.TYPE_MAP)) { + + // maps are converted to a ObjectNode. called recursively to traverse + // the entire object graph within the map. + ObjectNode convertedMap = JSON_NODE_FACTORY.objectNode(); + ObjectNode jsonObject = (ObjectNode) value; + Iterator<?> keyIterator = jsonObject.fieldNames(); + while (keyIterator.hasNext()) { + Object key = keyIterator.next(); + + // no need to getValue() here as this is already a ObjectNode and should have type info + convertedMap.put(key.toString(), jsonObject.get(key.toString())); + } + + valueAndType.put(AtlasGraphSONTokens.VALUE, convertedMap); + } else { + + // this must be a primitive value or a complex object. if a complex + // object it will be handled by a call to toString and stored as a + // string value + putObject(valueAndType, AtlasGraphSONTokens.VALUE, value); + } + + // this goes back as a JSONObject with data type and value + returnValue = valueAndType; + } + + return returnValue; + } + + private static Object getTypedValueFromJsonNode(JsonNode node) { + Object theValue = null; + + if (node != null && !node.isNull()) { + if (node.isBoolean()) { + theValue = node.booleanValue(); + } else if (node.isDouble()) { + theValue = node.doubleValue(); + } else if (node.isFloatingPointNumber()) { + theValue = node.floatValue(); + } else if (node.isInt()) { + theValue = node.intValue(); + } else if (node.isLong()) { + theValue = node.longValue(); + } else if (node.isTextual()) { + theValue = node.textValue(); + } else if (node.isArray()) { + // this is an array so just send it back so that it can be + // reprocessed to its primitive components + theValue = node; + } else if (node.isObject()) { + // this is an object so just send it back so that it can be + // reprocessed to its primitive components + theValue = node; + } else { + theValue = node.textValue(); + } + } + + return theValue; + } + + private static List<Object> convertArrayToList(final Object value) { + final ArrayList<Object> list = new ArrayList<Object>(); + int arrlength = Array.getLength(value); + for (int i = 0; i < arrlength; i++) { + Object object = Array.get(value, i); + list.add(object); + } + return list; + } + + private static String determineType(final Object value) { + String type = AtlasGraphSONTokens.TYPE_STRING; + if (value == null) { + type = AtlasGraphSONTokens.TYPE_UNKNOWN; + } else if (value.getClass() == Double.class) { + type = AtlasGraphSONTokens.TYPE_DOUBLE; + } else if (value.getClass() == Float.class) { + type = AtlasGraphSONTokens.TYPE_FLOAT; + } else if (value.getClass() == Byte.class) { + type = AtlasGraphSONTokens.TYPE_BYTE; + } else if (value.getClass() == Short.class) { + type = AtlasGraphSONTokens.TYPE_SHORT; + } else if (value.getClass() == Integer.class) { + type = AtlasGraphSONTokens.TYPE_INTEGER; + } else if (value.getClass() == Long.class) { + type = AtlasGraphSONTokens.TYPE_LONG; + } else if (value.getClass() == Boolean.class) { + type = AtlasGraphSONTokens.TYPE_BOOLEAN; + } else if (value instanceof ArrayNode) { + type = AtlasGraphSONTokens.TYPE_LIST; + } else if (value instanceof ObjectNode) { + type = AtlasGraphSONTokens.TYPE_MAP; + } + + return type; + } + + static class ElementFactory { + + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/query/NativeTitan1GraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/query/NativeTitan1GraphQuery.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/query/NativeTitan1GraphQuery.java new file mode 100644 index 0000000..9dc175b --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/query/NativeTitan1GraphQuery.java @@ -0,0 +1,85 @@ +/** + * 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.repository.graphdb.titan1.query; + +import java.util.Collection; + +import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator; +import org.apache.atlas.repository.graphdb.AtlasVertex; +import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery; +import org.apache.atlas.repository.graphdb.titan1.Titan1Edge; +import org.apache.atlas.repository.graphdb.titan1.Titan1Graph; +import org.apache.atlas.repository.graphdb.titan1.Titan1GraphDatabase; +import org.apache.atlas.repository.graphdb.titan1.Titan1Vertex; +import org.apache.tinkerpop.gremlin.process.traversal.Compare; + +import com.thinkaurelius.titan.core.TitanGraphQuery; +import com.thinkaurelius.titan.core.TitanVertex; +import com.thinkaurelius.titan.core.attribute.Contain; +import com.thinkaurelius.titan.graphdb.query.TitanPredicate; + +/** + * Titan 1.0.0 implementation of NativeTitanGraphQuery. + */ +public class NativeTitan1GraphQuery implements NativeTitanGraphQuery<Titan1Vertex, Titan1Edge> { + + private Titan1Graph graph; + private TitanGraphQuery<?> query; + + public NativeTitan1GraphQuery(Titan1Graph graph) { + this.query = Titan1GraphDatabase.getGraphInstance().query(); + this.graph = graph; + } + + @Override + public Iterable<AtlasVertex<Titan1Vertex, Titan1Edge>> vertices() { + Iterable<TitanVertex> it = query.vertices(); + return graph.wrapVertices(it); + } + + @Override + public void in(String propertyName, Collection<? extends Object> values) { + query.has(propertyName, Contain.IN, values); + + } + + @Override + public void has(String propertyName, ComparisionOperator op, Object value) { + + Compare c = getGremlinPredicate(op); + TitanPredicate pred = TitanPredicate.Converter.convert(c); + query.has(propertyName, pred, value); + } + + private Compare getGremlinPredicate(ComparisionOperator op) { + switch (op) { + case EQUAL: + return Compare.eq; + case GREATER_THAN_EQUAL: + return Compare.gte; + case LESS_THAN_EQUAL: + return Compare.lte; + case NOT_EQUAL: + return Compare.neq; + + default: + throw new RuntimeException("Unsupported comparison operator:" + op); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/query/Titan1GraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/query/Titan1GraphQuery.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/query/Titan1GraphQuery.java new file mode 100644 index 0000000..826523b --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/query/Titan1GraphQuery.java @@ -0,0 +1,55 @@ +/** + * 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.repository.graphdb.titan1.query; + +import org.apache.atlas.repository.graphdb.AtlasGraphQuery; +import org.apache.atlas.repository.graphdb.titan.query.TitanGraphQuery; +import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery; +import org.apache.atlas.repository.graphdb.titan.query.NativeTitanQueryFactory; +import org.apache.atlas.repository.graphdb.titan1.Titan1Edge; +import org.apache.atlas.repository.graphdb.titan1.Titan1Graph; +import org.apache.atlas.repository.graphdb.titan1.Titan1Vertex; +/** + * Titan 1.0.0 implementation of TitanGraphQuery. + */ +public class Titan1GraphQuery extends TitanGraphQuery<Titan1Vertex, Titan1Edge> + implements NativeTitanQueryFactory<Titan1Vertex, Titan1Edge> { + + public Titan1GraphQuery(Titan1Graph graph, boolean isChildQuery) { + super(graph, isChildQuery); + } + + public Titan1GraphQuery(Titan1Graph graph) { + super(graph); + } + + @Override + public AtlasGraphQuery<Titan1Vertex, Titan1Edge> createChildQuery() { + return new Titan1GraphQuery((Titan1Graph) graph, true); + } + + @Override + protected NativeTitanQueryFactory<Titan1Vertex, Titan1Edge> getQueryFactory() { + return this; + } + + @Override + public NativeTitanGraphQuery<Titan1Vertex, Titan1Edge> createNativeTitanQuery() { + return new NativeTitan1GraphQuery((Titan1Graph) graph); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/BigDecimalSerializer.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/BigDecimalSerializer.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/BigDecimalSerializer.java new file mode 100644 index 0000000..c1a096d --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/BigDecimalSerializer.java @@ -0,0 +1,48 @@ +/** + * 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.repository.graphdb.titan1.serializer; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import com.thinkaurelius.titan.core.attribute.AttributeSerializer; +import com.thinkaurelius.titan.diskstorage.ScanBuffer; +import com.thinkaurelius.titan.diskstorage.WriteBuffer; +/** + * Serializer for BigDecimal values. + */ +public class BigDecimalSerializer implements AttributeSerializer<BigDecimal> { + + private final BigIntegerSerializer bigIntegerDelegate = new BigIntegerSerializer(); + + @Override + public BigDecimal read(ScanBuffer buffer) { + BigInteger unscaledVal = bigIntegerDelegate.read(buffer); + int scale = buffer.getInt(); + return new BigDecimal(unscaledVal, scale); + } + + @Override + public void write(WriteBuffer buffer, BigDecimal attribute) { + BigInteger unscaledVal = attribute.unscaledValue(); + int scale = attribute.scale(); + bigIntegerDelegate.write(buffer, unscaledVal); + buffer.putInt(scale); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/BigIntegerSerializer.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/BigIntegerSerializer.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/BigIntegerSerializer.java new file mode 100644 index 0000000..dfda9f6 --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/BigIntegerSerializer.java @@ -0,0 +1,46 @@ +/** + * 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.repository.graphdb.titan1.serializer; + +import java.math.BigInteger; + +import com.thinkaurelius.titan.core.attribute.AttributeSerializer; +import com.thinkaurelius.titan.diskstorage.ScanBuffer; +import com.thinkaurelius.titan.diskstorage.WriteBuffer; +import com.thinkaurelius.titan.graphdb.database.serialize.attribute.ByteArraySerializer; + +/** + * Serializer for BigInteger values. + */ +public class BigIntegerSerializer implements AttributeSerializer<BigInteger> { + + private final ByteArraySerializer delegate = new ByteArraySerializer(); + + @Override + public BigInteger read(ScanBuffer buffer) { + byte[] value = delegate.read(buffer); + return new BigInteger(value); + } + + @Override + public void write(WriteBuffer buffer, BigInteger attribute) { + byte[] value = attribute.toByteArray(); + delegate.write(buffer, value); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/StringListSerializer.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/StringListSerializer.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/StringListSerializer.java new file mode 100644 index 0000000..eb99fae --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/StringListSerializer.java @@ -0,0 +1,53 @@ +/** + * 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.repository.graphdb.titan1.serializer; + +import java.util.ArrayList; +import java.util.List; + +import com.thinkaurelius.titan.core.attribute.AttributeSerializer; +import com.thinkaurelius.titan.diskstorage.ScanBuffer; +import com.thinkaurelius.titan.diskstorage.WriteBuffer; +import com.thinkaurelius.titan.graphdb.database.idhandling.VariableLong; +import com.thinkaurelius.titan.graphdb.database.serialize.attribute.StringSerializer; +/** + * Serializer for String lists. + */ +public class StringListSerializer implements AttributeSerializer<List<String>> { + + private final StringSerializer stringSerializer = new StringSerializer(); + + @Override + public List<String> read(ScanBuffer buffer) { + int length = (int)VariableLong.readPositive(buffer); + List<String> result = new ArrayList<String>(length); + for(int i = 0; i < length; i++) { + result.add(stringSerializer.read(buffer)); + } + return result; + } + + @Override + public void write(WriteBuffer buffer, List<String> attributes) { + VariableLong.writePositive(buffer, attributes.size()); + for(String attr : attributes) { + stringSerializer.write(buffer, attr); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/TypeCategorySerializer.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/TypeCategorySerializer.java b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/TypeCategorySerializer.java new file mode 100644 index 0000000..c3e2d1c --- /dev/null +++ b/graphdb/titan1/src/main/java/org/apache/atlas/repository/graphdb/titan1/serializer/TypeCategorySerializer.java @@ -0,0 +1,31 @@ +/** + * 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.repository.graphdb.titan1.serializer; + +import org.apache.atlas.typesystem.types.DataTypes.TypeCategory; + +import com.thinkaurelius.titan.graphdb.database.serialize.attribute.EnumSerializer; + +/** + * Serializer for TypeCategory value. + */ +public class TypeCategorySerializer extends EnumSerializer<TypeCategory> { + public TypeCategorySerializer() { + super(TypeCategory.class); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/graphdb/titan1/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory new file mode 100644 index 0000000..24c8a75 --- /dev/null +++ b/graphdb/titan1/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory @@ -0,0 +1 @@ +org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngineFactory http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6fd04d9a/graphdb/titan1/src/test/java/org/apache/atlas/repository/graphdb/titan1/AbstractGraphDatabaseTest.java ---------------------------------------------------------------------- diff --git a/graphdb/titan1/src/test/java/org/apache/atlas/repository/graphdb/titan1/AbstractGraphDatabaseTest.java b/graphdb/titan1/src/test/java/org/apache/atlas/repository/graphdb/titan1/AbstractGraphDatabaseTest.java new file mode 100644 index 0000000..7f3a436 --- /dev/null +++ b/graphdb/titan1/src/test/java/org/apache/atlas/repository/graphdb/titan1/AbstractGraphDatabaseTest.java @@ -0,0 +1,191 @@ +/** + * 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.repository.graphdb.titan1; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.atlas.repository.Constants; +import org.apache.atlas.repository.graphdb.AtlasCardinality; +import org.apache.atlas.repository.graphdb.AtlasGraph; +import org.apache.atlas.repository.graphdb.AtlasGraphManagement; +import org.apache.atlas.repository.graphdb.AtlasPropertyKey; +import org.apache.atlas.repository.graphdb.AtlasVertex; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; + +/** + * + */ +public abstract class AbstractGraphDatabaseTest { + + protected static final String WEIGHT_PROPERTY = "weight"; + protected static final String TRAIT_NAMES = Constants.TRAIT_NAMES_PROPERTY_KEY; + protected static final String TYPE_PROPERTY_NAME = "__type"; + protected static final String TYPESYSTEM = "TYPESYSTEM"; + + private static final String BACKING_INDEX_NAME = "backing"; + + private AtlasGraph<?, ?> graph = null; + + + public AbstractGraphDatabaseTest() { + super(); + } + + @BeforeClass + public static void createIndices() { + Titan1GraphDatabase db = new Titan1GraphDatabase(); + AtlasGraphManagement mgmt = db.getGraph().getManagementSystem(); + + if (mgmt.getGraphIndex(BACKING_INDEX_NAME) == null) { + mgmt.createVertexIndex(BACKING_INDEX_NAME, Constants.BACKING_INDEX, + Collections.<AtlasPropertyKey>emptyList()); + } + mgmt.makePropertyKey("age13", Integer.class, AtlasCardinality.SINGLE); + + createIndices(mgmt, "name", String.class, false, AtlasCardinality.SINGLE); + createIndices(mgmt, WEIGHT_PROPERTY, Integer.class, false, AtlasCardinality.SINGLE); + createIndices(mgmt, "size15", String.class, false, AtlasCardinality.SINGLE); + createIndices(mgmt, "typeName", String.class, false, AtlasCardinality.SINGLE); + createIndices(mgmt, "__type", String.class, false, AtlasCardinality.SINGLE); + createIndices(mgmt, Constants.GUID_PROPERTY_KEY, String.class, true, AtlasCardinality.SINGLE); + createIndices(mgmt, Constants.TRAIT_NAMES_PROPERTY_KEY, String.class, false, AtlasCardinality.SET); + createIndices(mgmt, Constants.SUPER_TYPES_PROPERTY_KEY, String.class, false, AtlasCardinality.SET); + mgmt.commit(); + } + + @AfterMethod + public void commitGraph() { + //force any pending actions to be committed so we can be sure they don't cause errors. + pushChangesAndFlushCache(); + getGraph().commit(); + } + + @AfterClass + public static void cleanUp() { + Titan1Graph graph = new Titan1Graph(); + graph.clear(); + + } + + protected <V, E> void pushChangesAndFlushCache() { + getGraph().commit(); + } + + private static void createIndices(AtlasGraphManagement management, String propertyName, Class propertyClass, + boolean isUnique, AtlasCardinality cardinality) { + + if (management.containsPropertyKey(propertyName)) { + //index was already created + return; + } + + AtlasPropertyKey key = management.makePropertyKey(propertyName, propertyClass, cardinality); + try { + if (propertyClass != Integer.class) { + management.addVertexIndexKey(BACKING_INDEX_NAME, key); + } + } catch(Throwable t) { + //ok + t.printStackTrace(); + } + try { + management.createExactMatchIndex(propertyName, isUnique, Collections.singletonList(key)); + + } catch(Throwable t) { + //ok + t.printStackTrace(); + } + + + } + + + + + protected final <V, E> AtlasGraph<V, E> getGraph() { + if (graph == null) { + graph = new Titan1Graph(); + } + return (AtlasGraph<V, E>)graph; + } + + protected Titan1Graph getTitan1Graph() { + AtlasGraph g = getGraph(); + return (Titan1Graph)g; + } + + + protected List<AtlasVertex> newVertices = new ArrayList<>(); + + protected final <V, E> AtlasVertex<V, E> createVertex(AtlasGraph<V, E> theGraph) { + AtlasVertex<V, E> vertex = theGraph.addVertex(); + newVertices.add(vertex); + return vertex; + } + + @AfterMethod + public void removeVertices() { + for(AtlasVertex vertex : newVertices) { + if (vertex.exists()) { + getGraph().removeVertex(vertex); + } + } + getGraph().commit(); + newVertices.clear(); + } + protected void runSynchronouslyInNewThread(final Runnable r) throws Throwable { + + RunnableWrapper wrapper = new RunnableWrapper(r); + Thread th = new Thread(wrapper); + th.start(); + th.join(); + Throwable ex = wrapper.getExceptionThrown(); + if (ex != null) { + throw ex; + } + } + + private static final class RunnableWrapper implements Runnable { + private final Runnable r; + private Throwable exceptionThrown = null; + + private RunnableWrapper(Runnable r) { + this.r = r; + } + + @Override + public void run() { + try { + r.run(); + } catch(Throwable e) { + exceptionThrown = e; + } + + } + + public Throwable getExceptionThrown() { + return exceptionThrown; + } + } + +}
