/*
* Copyright 2015-2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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.
*/
package org.hawkular.inventory.impl.tinkerpop;
import java.util.ServiceLoader;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.hawkular.inventory.api.Configuration;
import org.hawkular.inventory.base.BaseInventory;
import org.hawkular.inventory.base.TransactionConstructor;
import org.hawkular.inventory.base.spi.InventoryBackend;
import org.hawkular.inventory.impl.tinkerpop.spi.Constants;
import org.hawkular.inventory.impl.tinkerpop.spi.GraphProvider;
import org.hawkular.inventory.impl.tinkerpop.spi.IndexSpec;
/**
* @author Lukas Krejci
* @since 0.1.0
*/
public final class TinkerpopInventory extends BaseInventory<Element> {
public static final Configuration.Property GRAPH_PROVIDER_IMPL_CLASS = Configuration.Property.builder()
.withPropertyNameAndSystemProperty("hawkular.inventory.tinkerpop.graph-provider-impl")
.withEnvironmentVariables("HAWKULAR_INVENTORY_TINKERPOP_GRAPH_PROVIDER_IMPL").build();
public TinkerpopInventory() {
}
private TinkerpopInventory(BaseInventory<Element> orig, InventoryBackend<Element> backend,
TransactionConstructor<Element> transactionConstructor) {
super(orig, backend, transactionConstructor);
}
@Override protected TinkerpopInventory cloneWith(TransactionConstructor<Element> transactionCtor) {
return new TinkerpopInventory(this, null, transactionCtor);
}
@Override
protected InventoryBackend<Element> doInitialize(Configuration configuration) {
InventoryContext context = loadGraph(configuration);
return new TinkerpopBackend(context);
}
private InventoryContext loadGraph(Configuration configuration) {
GraphProvider gp = instantiateGraphProvider(configuration);
Log.LOG.iUsingGraphProvider(gp.getClass().getName());
Graph g = ensureIndices(gp, configuration);
return new InventoryContext(this, g, gp);
}
private Graph ensureIndices(GraphProvider graphProvider, Configuration config) {
Graph graph = graphProvider.instantiateGraph(config);
graphProvider.ensureIndices(graph,
IndexSpec.builder()
.withElementType(Vertex.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__cp.name())
.withType(String.class)
.withUnique(true)
// this breaks the resource-metric association in REST (not sure why)
// .withLabelIndex(Relationships.WellKnown.contains.name())
.build())
.withUnique(true)
.build(),
IndexSpec.builder()
.withElementType(Vertex.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__eid.name())
.withType(String.class)
// .withUnique(true)
.build())
.build(),
IndexSpec.builder()
.withElementType(Vertex.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__type.name())
.withType(String.class)
// .withUnique(true)
.build())
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__eid.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Vertex.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__type.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Vertex.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__type.name())
.withType(String.class)
.build())
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__metric_data_type.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__eid.name())
.withType(String.class)
.withUnique(true)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__sourceCp.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__sourceEid.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__sourceType.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__targetCp.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__targetEid.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__targetType.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Vertex.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__identityHash.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__targetIdentityHash.name())
.withType(String.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__from.name())
.withType(Long.class)
.build())
.build(),
IndexSpec.builder()
.withElementType(Edge.class)
.withProperty(IndexSpec.Property.builder()
.withName(Constants.Property.__to.name())
.withType(Long.class)
.build())
.build());
return graph;
}
private GraphProvider instantiateGraphProvider(Configuration config) {
String implClass = config.getProperty(GRAPH_PROVIDER_IMPL_CLASS, null);
if (implClass != null) {
try {
return (GraphProvider) Class.forName(implClass).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new IllegalStateException("Could not instantiate graph provider class '" + implClass + "'.", e);
}
} else {
return ServiceLoader.load(GraphProvider.class).iterator().next();
}
}
}