diff options
author | michaere <michaere@amdocs.com> | 2018-03-05 16:33:32 +0000 |
---|---|---|
committer | michaere <michaere@amdocs.com> | 2018-03-07 11:17:22 +0000 |
commit | c74f7b13b573386e70c10721fc391624ee792ed6 (patch) | |
tree | b44995474ff938b4b03c9b234f95b71bc75d6b79 /champ-lib/champ-janus | |
parent | 9fc28cff11a4b570618c0f533ce9de6209a5dd0c (diff) |
Port champ-microservice project restructure
Includes project restructure and introduction of a parent pom. The
original source folder and core functionality is now held within champ-lib, with champ-service
forming the ajsc microservice from which it injects champ-lib core
functionality.
Issue-ID: AAI-813
Change-Id: I2ce0c4a70e485665276e7955572de23969deb706
Signed-off-by: michaere <michaere@amdocs.com>
Diffstat (limited to 'champ-lib/champ-janus')
10 files changed, 1034 insertions, 0 deletions
diff --git a/champ-lib/champ-janus/License.txt b/champ-lib/champ-janus/License.txt new file mode 100644 index 0000000..469f362 --- /dev/null +++ b/champ-lib/champ-janus/License.txt @@ -0,0 +1,21 @@ +============LICENSE_START========================================== +org.onap.aai +=================================================================== +Copyright © 2017 AT&T Intellectual Property. All rights reserved. +Copyright © 2017 Amdocs +=================================================================== +Licensed 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. +============LICENSE_END============================================ +ECOMP is a trademark and service mark of AT&T Intellectual Property. + + diff --git a/champ-lib/champ-janus/pom.xml b/champ-lib/champ-janus/pom.xml new file mode 100644 index 0000000..15c65e5 --- /dev/null +++ b/champ-lib/champ-janus/pom.xml @@ -0,0 +1,188 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <artifactId>champ-lib</artifactId> + <groupId>org.onap.aai</groupId> + <version>1.2.0-SNAPSHOT</version> + </parent> + + <artifactId>champ-janus</artifactId> + + <properties> + <tinkerpop.version>3.2.3</tinkerpop.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>tinkergraph-gremlin</artifactId> + <version>${tinkerpop.version}</version> + </dependency> + <dependency> + <groupId>org.onap.aai</groupId> + <artifactId>champ-core</artifactId> + <version>1.2.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.onap.aai</groupId> + <artifactId>champ-core</artifactId> + <version>1.2.0-SNAPSHOT</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.janusgraph</groupId> + <artifactId>janusgraph-cassandra</artifactId> + <version>0.1.1</version> + <optional>true</optional> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + <exclusion> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </exclusion> + <exclusion> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-core</artifactId> + </exclusion> + <exclusion> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-groovy</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.janusgraph</groupId> + <artifactId>janusgraph-hbase</artifactId> + <version>0.1.1</version> + <optional>true</optional> + <exclusions> + <exclusion> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-groovy</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + <exclusion> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + </exclusion> + <exclusion> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-core</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.7.9</version> + <executions> + <execution> + <id>default-prepare-agent</id> + <goals> + <goal>prepare-agent</goal> + </goals> + </execution> + <execution> + <id>default-report</id> + <phase>prepare-package</phase> + <goals> + <goal>report</goal> + </goals> + </execution> + <execution> + <id>default-check</id> + <goals> + <goal>check</goal> + </goals> + <configuration> + <rules> + <!-- implementation is needed only for Maven 2 --> + <rule implementation="org.jacoco.maven.RuleConfiguration"> + <element>BUNDLE</element> + <limits> + <!-- implementation is needed only for Maven 2 --> + <limit implementation="org.jacoco.report.check.Limit"> + <counter>INSTRUCTION</counter> + <value>COVEREDRATIO</value> + <minimum>.15</minimum> + </limit> + <limit implementation="org.jacoco.report.check.Limit"> + <counter>BRANCH</counter> + <value>COVEREDRATIO</value> + <minimum>.14</minimum> + </limit> + <limit implementation="org.jacoco.report.check.Limit"> + <counter>COMPLEXITY</counter> + <value>COVEREDRATIO</value> + <minimum>.15</minimum> + </limit> + <limit implementation="org.jacoco.report.check.Limit"> + <counter>LINE</counter> + <value>COVEREDRATIO</value> + <minimum>.18</minimum> + </limit> + <limit implementation="org.jacoco.report.check.Limit"> + <counter>METHOD</counter> + <value>COVEREDRATIO</value> + <minimum>.10</minimum> + </limit> + <limit implementation="org.jacoco.report.check.Limit"> + <counter>CLASS</counter> + <value>MISSEDCOUNT</value> + <maximum>2</maximum> + </limit> + </limits> + </rule> + </rules> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>com.mycila</groupId> + <artifactId>license-maven-plugin</artifactId> + <version>3.0</version> + <configuration> + <header>License.txt</header> + <includes> + <include>**/*.java</include> + <include>**/*.ksh</include> + <include>**/*.sh</include> + <include>**/*.ftl</include> + <include>**/*.xsd</include> + <include>**/*.xjb</include> + <include>**/*.yml</include> + <include>**/*.yaml</include> + <include>**/aai*.xml</include> + <include>**/*logback*.xml</include> + <include>**/*aaiconfig*.properties</include> + <include>**/*titan*.properties</include> + </includes> + </configuration> + <executions> + <execution> + <goals> + <goal>format</goal> + </goals> + <phase>process-sources</phase> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/GraphSON.java b/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/GraphSON.java new file mode 100644 index 0000000..9e849b8 --- /dev/null +++ b/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/GraphSON.java @@ -0,0 +1,66 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed 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. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.graph.impl; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +// import com.thinkaurelius.titan.graphdb.tinkerpop.TitanIoRegistry; +import org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter; +import org.onap.aai.champcore.FormatMapper; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class GraphSON implements FormatMapper { + private final GraphSONMapper mapper; + private final GraphSONWriter writer; + protected JsonParser parser; + + public GraphSON() { + this.mapper = GraphSONMapper.build().addRegistry(JanusGraphIoRegistry.getInstance ()).create(); + this.writer = GraphSONWriter.build().mapper(this.mapper).create(); + this.parser = new JsonParser(); + } + + public JsonObject formatObject(Object v) { + OutputStream os = new ByteArrayOutputStream(); + String result = ""; + + try { + this.writer.writeVertex(os, (Vertex)v, Direction.BOTH); + result = os.toString(); + } catch (IOException var5) { + var5.printStackTrace(); + } + + return this.parser.parse(result).getAsJsonObject(); + } + + public int parallelThreshold() { + return 50; + } +} diff --git a/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/JanusChampGraphImpl.java b/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/JanusChampGraphImpl.java new file mode 100644 index 0000000..9ede7df --- /dev/null +++ b/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/JanusChampGraphImpl.java @@ -0,0 +1,493 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed 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. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.graph.impl; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.*; +import org.onap.aai.champcore.Formatter; +import org.janusgraph.core.schema.JanusGraphIndex; +import org.janusgraph.core.schema.JanusGraphManagement; +import org.janusgraph.core.schema.SchemaAction; +import org.janusgraph.core.schema.SchemaStatus; +import org.janusgraph.graphdb.database.management.ManagementSystem; +import org.onap.aai.champcore.ChampCapabilities; +import org.onap.aai.champcore.FormatMapper; +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.graph.impl.AbstractTinkerpopChampGraph; +import org.onap.aai.champcore.model.*; +import org.onap.aai.champcore.schema.ChampSchemaEnforcer; +import org.onap.aai.champcore.schema.DefaultChampSchemaEnforcer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public final class JanusChampGraphImpl extends AbstractTinkerpopChampGraph { + private static final Logger LOGGER = LoggerFactory.getLogger(JanusChampGraphImpl.class); + private static final String JANUS_CASSANDRA_KEYSPACE = "storage.cassandra.keyspace"; + private static final String JANUS_HBASE_TABLE = "storage.hbase.table"; + private static final String JANUS_UNIQUE_SUFFIX = "graph.unique-instance-id-suffix"; + private static final ChampSchemaEnforcer SCHEMA_ENFORCER = new DefaultChampSchemaEnforcer(); + private static final int REGISTER_OBJECT_INDEX_TIMEOUT_SECS = 30; + + private static final ChampCapabilities CAPABILITIES = new ChampCapabilities() { + + @Override + public boolean canDeleteObjectIndices() { + return false; + } + + @Override + public boolean canDeleteRelationshipIndices() { + return false; + } + }; + + private final JanusGraph graph; + + public JanusChampGraphImpl(Builder builder) { + super(builder.graphConfiguration); + final JanusGraphFactory.Builder janusGraphBuilder = JanusGraphFactory.build(); + + for (Map.Entry<String, Object> janusGraphProperty : builder.graphConfiguration.entrySet()) { + janusGraphBuilder.set(janusGraphProperty.getKey(), janusGraphProperty.getValue()); + } + + janusGraphBuilder.set(JANUS_UNIQUE_SUFFIX, ((short) new Random().nextInt(Short.MAX_VALUE)+"")); + + final Object storageBackend = builder.graphConfiguration.get("storage.backend"); + + if ("cassandra".equals(storageBackend) || + "cassandrathrift".equals(storageBackend) || + "astyanax".equals(storageBackend) || + "embeddedcassandra".equals(storageBackend)) { + + janusGraphBuilder.set(JANUS_CASSANDRA_KEYSPACE, builder.graphName); + } else if ("hbase".equals(storageBackend)) { + janusGraphBuilder.set(JANUS_HBASE_TABLE, builder.graphName); + } else if ("berkleyje".equals(storageBackend)) { + throw new RuntimeException("storage.backend=berkleyje cannot handle multiple graphs on a single DB, not usable"); + } else if ("inmemory".equals(storageBackend)) { + } else { + throw new RuntimeException("Unknown storage.backend=" + storageBackend); + } + + LOGGER.info("Instantiated data access layer for Janus graph data store with backend: " + storageBackend); + this.graph = janusGraphBuilder.open(); + } + + public static class Builder { + private final String graphName; + + private final Map<String, Object> graphConfiguration = new HashMap<String, Object>(); + + public Builder(String graphName) { + this.graphName = graphName; + } + + public Builder(String graphName, Map<String, Object> properties) { + this.graphName = graphName; + properties(properties); + } + + public Builder properties(Map<String, Object> properties) { + if (properties.containsKey(JANUS_CASSANDRA_KEYSPACE)) { + throw new IllegalArgumentException("Cannot use path " + JANUS_CASSANDRA_KEYSPACE + + " in initial configuration - this path is used" + + " to specify graph names"); + } + + this.graphConfiguration.putAll(properties); + return this; + } + + public Builder property(String path, Object value) { + if (path.equals(JANUS_CASSANDRA_KEYSPACE)) { + throw new IllegalArgumentException("Cannot use path " + JANUS_CASSANDRA_KEYSPACE + + " in initial configuration - this path is used" + + " to specify graph names"); + } + graphConfiguration.put(path, value); + return this; + } + + public JanusChampGraphImpl build() { + return new JanusChampGraphImpl(this); + } + } + + @Override + protected JanusGraph getGraph() { + return graph; + } + + + @Override + protected ChampSchemaEnforcer getSchemaEnforcer() { + return SCHEMA_ENFORCER; + } + + @Override + public void executeStoreObjectIndex(ChampObjectIndex index) { + if (isShutdown()) { + throw new IllegalStateException("Cannot call storeObjectIndex() after shutdown has been initiated"); + } + + final JanusGraph graph = getGraph(); + final JanusGraphManagement createIndexMgmt = graph.openManagement(); + final PropertyKey pk = createIndexMgmt.getOrCreatePropertyKey(index.getField().getName()); + + if (createIndexMgmt.getGraphIndex(index.getName()) != null) { + createIndexMgmt.rollback(); + return; //Ignore, index already exists + } + + createIndexMgmt.buildIndex(index.getName(), Vertex.class).addKey(pk).buildCompositeIndex(); + + createIndexMgmt.commit(); + graph.tx().commit(); + + awaitIndexCreation(index.getName()); + } + + @Override + public Optional<ChampObjectIndex> retrieveObjectIndex(String indexName) { + if (isShutdown()) { + throw new IllegalStateException("Cannot call retrieveObjectIndex() after shutdown has been initiated"); + } + + final JanusGraphManagement retrieveIndexMgmt = getGraph().openManagement(); + final JanusGraphIndex index = retrieveIndexMgmt.getGraphIndex(indexName); + + if (index == null) { + return Optional.empty(); + } + if (index.getIndexedElement() != JanusGraphVertex.class) { + return Optional.empty(); + } + + return Optional.of(ChampObjectIndex.create() + .ofName(indexName) + .onType(ChampObject.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build()); + } + + @Override + public Stream<ChampObjectIndex> retrieveObjectIndices() { + if (isShutdown()) { + throw new IllegalStateException("Cannot call retrieveObjectIndices() after shutdown has been initiated"); + } + + final JanusGraphManagement createIndexMgmt = getGraph().openManagement(); + final Iterator<JanusGraphIndex> indices = createIndexMgmt.getGraphIndexes(Vertex.class).iterator(); + + final Iterator<ChampObjectIndex> objIter = new Iterator<ChampObjectIndex>() { + + private ChampObjectIndex next; + + @Override + public boolean hasNext() { + if (indices.hasNext()) { + final JanusGraphIndex index = indices.next(); + + next = ChampObjectIndex.create() + .ofName(index.name()) + .onType(ChampObject.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build(); + return true; + } + + next = null; + return false; + } + + @Override + public ChampObjectIndex next() { + if (next == null) { + throw new NoSuchElementException(); + } + + return next; + } + }; + + return StreamSupport.stream(Spliterators.spliteratorUnknownSize( + objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); + } + + @Override + public void executeDeleteObjectIndex(String indexName) throws ChampIndexNotExistsException { + if (isShutdown()) { + throw new IllegalStateException("Cannot call deleteObjectIndex() after shutdown has been initiated"); + } + + throw new UnsupportedOperationException("Cannot delete indices using the JanusChampImpl"); + } + + @Override + public void executeStoreRelationshipIndex(ChampRelationshipIndex index) { + if (isShutdown()) { + throw new IllegalStateException("Cannot call storeRelationshipIndex() after shutdown has been initiated"); + } + + final JanusGraph graph = getGraph(); + final JanusGraphManagement createIndexMgmt = graph.openManagement(); + final PropertyKey pk = createIndexMgmt.getOrCreatePropertyKey(index.getField().getName()); + + if (createIndexMgmt.getGraphIndex(index.getName()) != null) { + return; //Ignore, index already exists + } + createIndexMgmt.buildIndex(index.getName(), Edge.class).addKey(pk).buildCompositeIndex(); + + createIndexMgmt.commit(); + graph.tx().commit(); + + awaitIndexCreation(index.getName()); + } + + @Override + public Optional<ChampRelationshipIndex> retrieveRelationshipIndex(String indexName) { + if (isShutdown()) { + throw new IllegalStateException("Cannot call retrieveRelationshipIndex() after shutdown has been initiated"); + } + + final JanusGraphManagement retrieveIndexMgmt = getGraph().openManagement(); + final JanusGraphIndex index = retrieveIndexMgmt.getGraphIndex(indexName); + + if (index == null) { + return Optional.empty(); + } + if (index.getIndexedElement() != JanusGraphEdge.class) { + return Optional.empty(); + } + + return Optional.of(ChampRelationshipIndex.create() + .ofName(indexName) + .onType(ChampObject.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build()); + } + + @Override + public Stream<ChampRelationshipIndex> retrieveRelationshipIndices() { + if (isShutdown()) { + throw new IllegalStateException("Cannot call retrieveRelationshipIndices() after shutdown has been initiated"); + } + + final JanusGraphManagement createIndexMgmt = getGraph().openManagement(); + final Iterator<JanusGraphIndex> indices = createIndexMgmt.getGraphIndexes(Edge.class).iterator(); + + final Iterator<ChampRelationshipIndex> objIter = new Iterator<ChampRelationshipIndex>() { + + private ChampRelationshipIndex next; + + @Override + public boolean hasNext() { + if (indices.hasNext()) { + final JanusGraphIndex index = indices.next(); + + next = ChampRelationshipIndex.create() + .ofName(index.name()) + .onType(ChampRelationship.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build(); + return true; + } + + next = null; + return false; + } + + @Override + public ChampRelationshipIndex next() { + if (next == null) { + throw new NoSuchElementException(); + } + + return next; + } + }; + + return StreamSupport.stream(Spliterators.spliteratorUnknownSize( + objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); + } + + @Override + public void executeDeleteRelationshipIndex(String indexName) throws ChampIndexNotExistsException { + if (isShutdown()) { + throw new IllegalStateException("Cannot call deleteRelationshipIndex() after shutdown has been initiated"); + } + + throw new UnsupportedOperationException("Cannot delete indices using the JanusChampImpl"); + } + + private Cardinality getJanusCardinality(ChampCardinality cardinality) { + switch (cardinality) { + case LIST: + return Cardinality.LIST; + case SET: + return Cardinality.SET; + case SINGLE: + return Cardinality.SINGLE; + default: + throw new RuntimeException("Unknown ChampCardinality " + cardinality); + } + } + + private void awaitIndexCreation(String indexName) { + //Wait for the index to become available + try { + if (ManagementSystem.awaitGraphIndexStatus(graph, indexName) + .status(SchemaStatus.ENABLED) + .timeout(1, ChronoUnit.SECONDS) + .call() + .getSucceeded()) { + return; //Empty graphs immediately ENABLE indices + } + + if (!ManagementSystem.awaitGraphIndexStatus(graph, indexName) + .status(SchemaStatus.REGISTERED) + .timeout(REGISTER_OBJECT_INDEX_TIMEOUT_SECS, ChronoUnit.SECONDS) + .call() + .getSucceeded()) { + LOGGER.warn("Object index was created, but timed out while waiting for it to be registered"); + return; + } + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while waiting for object index creation status"); + return; + } + + //Reindex the existing data + + try { + final JanusGraphManagement updateIndexMgmt = graph.openManagement(); + updateIndexMgmt.updateIndex(updateIndexMgmt.getGraphIndex(indexName), SchemaAction.REINDEX).get(); + updateIndexMgmt.commit(); + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while reindexing for object index"); + return; + } catch (ExecutionException e) { + LOGGER.warn("Exception occurred during reindexing procedure for creating object index " + indexName, e); + } + + try { + ManagementSystem.awaitGraphIndexStatus(graph, indexName) + .status(SchemaStatus.ENABLED) + .timeout(10, ChronoUnit.MINUTES) + .call(); + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while waiting for index to transition to ENABLED state"); + return; + } + } + + @Override + public ChampCapabilities capabilities() { + return CAPABILITIES; + } + + public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException { + if (isShutdown()) throw new IllegalStateException("Cannot call storeSchema() after shutdown has been initiated"); + + final ChampSchema currentSchema = retrieveSchema(); + final JanusGraphManagement mgmt = getGraph().openManagement(); + + try { + for (ChampObjectConstraint objConstraint : schema.getObjectConstraints().values()) { + for (ChampPropertyConstraint propConstraint : objConstraint.getPropertyConstraints()) { + final Optional<ChampObjectConstraint> currentObjConstraint = currentSchema.getObjectConstraint(objConstraint.getType()); + + if (currentObjConstraint.isPresent()) { + final Optional<ChampPropertyConstraint> currentPropConstraint = currentObjConstraint.get().getPropertyConstraint(propConstraint.getField().getName()); + + if (currentPropConstraint.isPresent() && currentPropConstraint.get().compareTo(propConstraint) != 0) { + throw new ChampSchemaViolationException("Cannot update already existing property on object type " + objConstraint.getType() + ": " + propConstraint); + } + } + + final String newPropertyKeyName = propConstraint.getField().getName(); + + if (mgmt.getPropertyKey(newPropertyKeyName) != null) continue; //Check Janus to see if another node created this property key + + mgmt.makePropertyKey(newPropertyKeyName) + .dataType(propConstraint.getField().getJavaType()) + .cardinality(getJanusCardinality(propConstraint.getCardinality())) + .make(); + } + } + + for (ChampRelationshipConstraint relConstraint : schema.getRelationshipConstraints().values()) { + + final Optional<ChampRelationshipConstraint> currentRelConstraint = currentSchema.getRelationshipConstraint(relConstraint.getType()); + + for (ChampPropertyConstraint propConstraint : relConstraint.getPropertyConstraints()) { + + if (currentRelConstraint.isPresent()) { + final Optional<ChampPropertyConstraint> currentPropConstraint = currentRelConstraint.get().getPropertyConstraint(propConstraint.getField().getName()); + + if (currentPropConstraint.isPresent() && currentPropConstraint.get().compareTo(propConstraint) != 0) { + throw new ChampSchemaViolationException("Cannot update already existing property on relationship type " + relConstraint.getType()); + } + } + + final String newPropertyKeyName = propConstraint.getField().getName(); + + if (mgmt.getPropertyKey(newPropertyKeyName) != null) continue; //Check Janus to see if another node created this property key + + mgmt.makePropertyKey(newPropertyKeyName) + .dataType(propConstraint.getField().getJavaType()) + .cardinality(getJanusCardinality(propConstraint.getCardinality())) + .make(); + } + + final EdgeLabel edgeLabel = mgmt.getEdgeLabel(relConstraint.getType()); + + if (edgeLabel != null) { + mgmt.makeEdgeLabel(relConstraint.getType()) + .directed() + .make(); + } + } + + mgmt.commit(); + + super.storeSchema(schema); + } catch (SchemaViolationException | ChampSchemaViolationException e) { + mgmt.rollback(); + throw new ChampSchemaViolationException(e); + } + } + + public GraphTraversal<?, ?> hasLabel(GraphTraversal<?, ?> query, Object type) { + return query.hasLabel(type); + } +}
\ No newline at end of file diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/concurrency/ConcurrencyTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/concurrency/ConcurrencyTest.java new file mode 100644 index 0000000..68e1a1a --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/concurrency/ConcurrencyTest.java @@ -0,0 +1,33 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed 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. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.concurrency; + +import org.junit.Test; + +public class ConcurrencyTest { + + @Test + public void runInMemoryConcurrentTest() { + org.onap.aai.champcore.concurrency.ConcurrencyTest baseTest = new org.onap.aai.champcore.concurrency.ConcurrencyTest(); + baseTest.runConcurrentTest("JANUS"); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampAPITest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampAPITest.java new file mode 100644 index 0000000..4fd9e4a --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampAPITest.java @@ -0,0 +1,38 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed 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. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Test; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +public class ChampAPITest { + @Test + public void testChampGraphInstantiation() throws Exception { + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + + org.onap.aai.champcore.core.ChampAPITest baseTest = new org.onap.aai.champcore.core.ChampAPITest(); + + baseTest.testChampGraphInstantiation(graph); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampObjectIndexTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampObjectIndexTest.java new file mode 100644 index 0000000..bd031ef --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampObjectIndexTest.java @@ -0,0 +1,46 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed 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. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +public class ChampObjectIndexTest { + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test + public void testChampObjectIndexCrud() throws Exception { + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + + org.onap.aai.champcore.core.ChampObjectIndexTest.testChampObjectIndexCrud(graph); + + graph.shutdown(); + + exception.expect(IllegalStateException.class); + graph.executeDeleteObjectIndex("any"); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampRelationshipIndexTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampRelationshipIndexTest.java new file mode 100644 index 0000000..bbfb585 --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampRelationshipIndexTest.java @@ -0,0 +1,38 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed 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. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Test; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +public class ChampRelationshipIndexTest { + @Test + public void testChampRelationshipIndexCrud() { + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + org.onap.aai.champcore.core.ChampRelationshipIndexTest baseTest = new org.onap.aai.champcore.core.ChampRelationshipIndexTest(); + baseTest.testChampRelationshipIndexCrud(graph); + + graph.shutdown(); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampSchemaTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampSchemaTest.java new file mode 100644 index 0000000..96ffb25 --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampSchemaTest.java @@ -0,0 +1,37 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed 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. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Test; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +public class ChampSchemaTest { + @Test + public void testChampSchemaCrud() { + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + org.onap.aai.champcore.core.ChampSchemaTest.testChampSchemaCrud(graph); + + graph.shutdown(); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/JanusChampSetupTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/JanusChampSetupTest.java new file mode 100644 index 0000000..3cca54d --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/JanusChampSetupTest.java @@ -0,0 +1,74 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed 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. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +import java.util.HashMap; +import java.util.Map; + +public class JanusChampSetupTest { + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test + public void JanusSetupBadBackendTest() { + exception.expect(RuntimeException.class); + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "bad-backend") + .build(); + } + + @Test + public void JanusSetupBerkleyBackendTest() { + exception.expect(RuntimeException.class); + Map<String, Object> propertiesMap = new HashMap<String, Object>(); + propertiesMap.put("storage.backend", "berkleyje"); + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .properties(propertiesMap) + .build(); + } + + @Test + public void JanusSetupBadPropertyTest() { + exception.expect(RuntimeException.class); + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "in-memory") + .property("storage.cassandra.keyspace", "anything") + .build(); + } + + @Test + public void JanusSetupBadPropertiesTest() { + exception.expect(RuntimeException.class); + Map<String, Object> propertiesMap = new HashMap<String, Object>(); + propertiesMap.put("storage.cassandra.keyspace", "anything"); + + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "in-memory") + .properties(propertiesMap) + .build(); + } +} |