project_category: ''
lifecycle_state: 'Incubation'
project_lead: &onap_aai_ptl
- name: 'James Forsyth'
- email: 'jf2512@att.com'
- id: 'jimmydot'
+ name: 'William Reehil'
+ email: 'william.reehil@att.com'
company: 'ATT'
- timezone: 'America/Detroit'
+ id: 'wreehil'
+ timezone: 'America/New_York'
primary_contact: *onap_aai_ptl
issue_tracking:
type: 'jira'
company: 'ATT'
id: 'vk250x'
timezone: 'America/New_York'
+ - name: 'James Forsyth'
+ email: 'jf2512@att.com'
+ id: 'jimmydot'
+ company: 'ATT'
+ timezone: 'America/Detroit'
tsc:
approval: 'https://lists.onap.org/g/onap-tsc'
changes:
- type: 'removal'
name: 'Tian Lee'
link: 'https://lists.onap.org/g/onap-tsc/message/6227'
+ - type: 'Addition'
+ name: 'William Reehil'
+ link: 'https://lists.onap.org/g/onap-tsc/message/6506'
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
import com.google.common.collect.Multimap;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.janusgraph.core.Cardinality;
-import org.janusgraph.core.JanusGraph;
import org.janusgraph.core.Multiplicity;
import org.janusgraph.core.PropertyKey;
import org.janusgraph.core.schema.JanusGraphManagement;
import org.onap.aai.edges.EdgeRule;
import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
import org.onap.aai.introspection.Introspector;
-import org.onap.aai.introspection.Loader;
import org.onap.aai.introspection.LoaderUtil;
import org.onap.aai.logging.LogFormatTools;
import org.onap.aai.schema.enums.PropertyMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
public class SchemaGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger(SchemaGenerator.class);
private SchemaGenerator() {
-
}
/**
* @param graphMgmt
* the graph mgmt
*/
- public static void loadSchemaIntoJanusGraph(final JanusGraphManagement graphMgmt,
- String backend) {
+ public static void loadSchemaIntoJanusGraph(final JanusGraphManagement graphMgmt, String backend) {
try {
AAIConfig.init();
} catch (Exception ex) {
- LOGGER.error(" ERROR - Could not run AAIConfig.init(). " + LogFormatTools.getStackTop(ex));
+ LOGGER.error(" ERROR - Could not run AAIConfig.init(). {}", LogFormatTools.getStackTop(ex));
System.exit(1);
}
// multiplicty definitions depends on which two types of nodes are being
// connected.
- Multimap<String, EdgeRule> edges = null;
- Set<String> labels = new HashSet<>();
-
- EdgeIngestor edgeIngestor = SpringContextAware.getBean(EdgeIngestor.class);
-
- try {
- edges = edgeIngestor.getAllCurrentRules();
- } catch (EdgeRuleNotFoundException e) {
- LOGGER.error("Unable to find all rules {}", LogFormatTools.getStackTop(e));
- }
-
- for (EdgeRule rule : edges.values()) {
- labels.add(rule.getLabel());
- }
+ makeEdgeLabels(graphMgmt);
- for (String label : labels) {
- if (graphMgmt.containsRelationType(label)) {
- String dmsg = " EdgeLabel [" + label + "] already existed. ";
- LOGGER.debug(dmsg);
- } else {
- String dmsg = "Making EdgeLabel: [" + label + "]";
- LOGGER.debug(dmsg);
- graphMgmt.makeEdgeLabel(label).multiplicity(Multiplicity.valueOf("MULTI")).make();
- }
- }
- Loader loader = LoaderUtil.getLatestVersion();
-
- Map<String, Introspector> objs = loader.getAllObjects();
+ Map<String, Introspector> objs = LoaderUtil.getLatestVersion().getAllObjects();
Map<String, PropertyKey> seenProps = new HashMap<>();
for (Introspector obj : objs.values()) {
dbPropName = alias.get();
}
if (graphMgmt.containsRelationType(dbPropName)) {
- String dmsg = " PropertyKey [" + dbPropName + "] already existed in the DB. ";
- LOGGER.debug(dmsg);
+ LOGGER.debug(" PropertyKey [{}] already existed in the DB. ", dbPropName);
} else {
Class<?> type = obj.getClass(propName);
Cardinality cardinality = Cardinality.SINGLE;
if (process) {
- String imsg = "Creating PropertyKey: [" + dbPropName + "], [" + type.getSimpleName() + "], ["
- + cardinality + "]";
- LOGGER.info(imsg);
+ LOGGER.info("Creating PropertyKey: [{}], [{}], [{}]",
+ dbPropName, type.getSimpleName(), cardinality);
PropertyKey propK;
if (!seenProps.containsKey(dbPropName)) {
propK = graphMgmt.makePropertyKey(dbPropName).dataType(type).cardinality(cardinality)
propK = seenProps.get(dbPropName);
}
if (graphMgmt.containsGraphIndex(dbPropName)) {
- String dmsg = " Index [" + dbPropName + "] already existed in the DB. ";
- LOGGER.debug(dmsg);
+ LOGGER.debug(" Index [{}] already existed in the DB. ", dbPropName);
} else {
if (obj.getIndexedProperties().contains(propName)) {
if (obj.getUniqueProperties().contains(propName)) {
- imsg = "Add Unique index for PropertyKey: [" + dbPropName + "]";
- LOGGER.info(imsg);
+ LOGGER.info("Add Unique index for PropertyKey: [{}]", dbPropName);
graphMgmt.buildIndex(dbPropName, Vertex.class).addKey(propK).unique()
.buildCompositeIndex();
} else {
- imsg = "Add index for PropertyKey: [" + dbPropName + "]";
- LOGGER.info(imsg);
+ LOGGER.info("Add index for PropertyKey: [{}]", dbPropName);
graphMgmt.buildIndex(dbPropName, Vertex.class).addKey(propK).buildCompositeIndex();
}
} else {
- imsg = "No index added for PropertyKey: [" + dbPropName + "]";
- LOGGER.info(imsg);
+ LOGGER.info("No index added for PropertyKey: [{}]", dbPropName);
}
}
}
}
}
- String imsg = "-- About to call graphMgmt commit";
- LOGGER.info(imsg);
+ LOGGER.info("-- About to call graphMgmt commit");
if (backend != null) {
- LOGGER.info(String.format("Successfully loaded the schema to %s", backend));
+ LOGGER.info("Successfully loaded the schema to {}", backend);
}
graphMgmt.commit();
}
+ private static void makeEdgeLabels(JanusGraphManagement graphMgmt) {
+ try {
+ EdgeIngestor edgeIngestor = SpringContextAware.getBean(EdgeIngestor.class);
+
+ Set<String> labels = Optional.ofNullable(edgeIngestor.getAllCurrentRules())
+ .map(collectValues(EdgeRule::getLabel))
+ .orElseGet(HashSet::new);
+
+ labels.forEach(label -> {
+ if (graphMgmt.containsRelationType(label)) {
+ LOGGER.debug(" EdgeLabel [{}] already existed. ", label);
+ } else {
+ LOGGER.debug("Making EdgeLabel: [{}]", label);
+ graphMgmt.makeEdgeLabel(label).multiplicity(Multiplicity.valueOf("MULTI")).make();
+ }
+ });
+ } catch (EdgeRuleNotFoundException e) {
+ LOGGER.error("Unable to find all rules {}", LogFormatTools.getStackTop(e));
+ }
+ }
+
+ /**
+ * Returns a function collecting all the values in a {@link com.google.common.collect.Multimap}
+ * given a mapping function
+ *
+ * @param f The mapper function
+ * @param <K> The type of key used by the provided {@link com.google.common.collect.Multimap}
+ * @param <V> The type of value used by the provided {@link com.google.common.collect.Multimap}
+ * @param <V0> The type which <V> is mapped to
+ */
+ private static <K, V, V0> Function<Multimap<K, V>, Set<V0>> collectValues(Function<V, V0> f) {
+ return as -> as.values().stream().map(f).collect(Collectors.toSet());
+ }
+
}
package org.onap.aai.dbgen;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import com.google.common.collect.Multimap;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.janusgraph.core.Cardinality;
-import org.janusgraph.core.JanusGraph;
import org.janusgraph.core.Multiplicity;
import org.janusgraph.core.PropertyKey;
import org.janusgraph.core.schema.JanusGraphManagement;
import org.onap.aai.logging.LogFormatTools;
import org.onap.aai.schema.enums.PropertyMetadata;
import org.onap.aai.util.AAIConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import java.util.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
import static org.onap.aai.db.props.AAIProperties.*;
private static final Logger LOGGER = LoggerFactory.getLogger(SchemaGenerator4Hist.class);
+ private SchemaGenerator4Hist(){
+
+ }
/**
* Load schema into JanusGraph.
*
- * @param graph
- * the graph
* @param graphMgmt
* the graph mgmt
*/
- public static void loadSchemaIntoJanusGraph(final JanusGraph graph, final JanusGraphManagement graphMgmt,
- String backend) {
+ public static void loadSchemaIntoJanusGraph(final JanusGraphManagement graphMgmt, String backend) {
try {
AAIConfig.init();
} catch (Exception ex) {
- LOGGER.error(" ERROR - Could not run AAIConfig.init(). " + LogFormatTools.getStackTop(ex));
- // System.out.println(" ERROR - Could not run AAIConfig.init(). ");
+ LOGGER.error(" ERROR - Could not run AAIConfig.init(). {}", LogFormatTools.getStackTop(ex));
System.exit(1);
}
for (String label : labels) {
if (graphMgmt.containsRelationType(label)) {
- String dmsg = " EdgeLabel [" + label + "] already existed. ";
- LOGGER.debug(dmsg);
+ LOGGER.debug(" EdgeLabel [{}] already existed. ", label);
} else {
- String dmsg = "Making EdgeLabel: [" + label + "]";
- LOGGER.debug(dmsg);
+ LOGGER.debug("Making EdgeLabel: [{}]", label);
graphMgmt.makeEdgeLabel(label).multiplicity(Multiplicity.valueOf("MULTI")).make();
}
}
dbPropName = alias.get();
}
if (graphMgmt.containsRelationType(dbPropName)) {
- String dmsg = " PropertyKey [" + dbPropName + "] already existed in the DB. ";
- LOGGER.debug(dmsg);
+ LOGGER.debug(" PropertyKey [{}] already existed in the DB. ", dbPropName);
} else {
Class<?> type = obj.getClass(propName);
Cardinality cardinality = Cardinality.LIST;
// above) will be stored in our db as a single String. And that
// single string will have Cardinality = LIST so we can track its
// history.
- //cardinality = Cardinality.SET;
type = obj.getGenericTypeClass(propName);
process = true;
} else if (obj.isSimpleType(propName)) {
if (process) {
- String imsg = " Creating PropertyKey: [" + dbPropName + "], [" + type.getSimpleName() + "], ["
- + cardinality + "]";
- LOGGER.info(imsg);
+ LOGGER.info(" Creating PropertyKey: [{}], [{}], [{}]",
+ dbPropName, type.getSimpleName(), cardinality);
PropertyKey propK;
if (!seenProps.containsKey(dbPropName)) {
propK = graphMgmt.makePropertyKey(dbPropName).dataType(type).cardinality(cardinality)
propK = seenProps.get(dbPropName);
}
if (graphMgmt.containsGraphIndex(dbPropName)) {
- String dmsg = " Index [" + dbPropName + "] already existed in the DB. ";
- LOGGER.debug(dmsg);
+ LOGGER.debug(" Index [{}] already existed in the DB. ", dbPropName);
} else {
if (obj.getIndexedProperties().contains(propName)) {
// NOTE - for History we never add a unique index - just a regular index
- imsg = "Add index for PropertyKey: [" + dbPropName + "]";
- LOGGER.info(imsg);
+ LOGGER.info("Add index for PropertyKey: [{}]", dbPropName);
graphMgmt.buildIndex(dbPropName, Vertex.class).addKey(propK).buildCompositeIndex();
} else {
- imsg = "No index needed/added for PropertyKey: [" + dbPropName + "]";
- LOGGER.info(imsg);
+ LOGGER.info("No index needed/added for PropertyKey: [{}]", dbPropName);
}
}
}
// only have one of them. That is, a Property can show up many times in a
// node, but each instance of that property will only have a single start-ts,
// end-ts, end-source-of-truth. Same goes for a node or edge itself.
- if (graphMgmt.containsRelationType(END_SOT)) {
- String dmsg = "PropertyKey [" + END_SOT + "] already existed in the DB. ";
- LOGGER.debug(dmsg);
- } else if (!seenProps.containsKey(END_SOT) ) {
- String imsg = " Creating PropertyKey: [" + END_SOT + "], [String], [SINGLE]";
- LOGGER.info(imsg);
- graphMgmt.makePropertyKey(END_SOT).dataType(String.class)
- .cardinality(Cardinality.SINGLE).make();
- }
-
- if (graphMgmt.containsRelationType(START_TS)) {
- String dmsg = " PropertyKey [" + START_TS + "] already existed in the DB. ";
- LOGGER.debug(dmsg);
- } else if (!seenProps.containsKey(START_TS) ) {
- String imsg = " Creating PropertyKey: [" + START_TS + "], [Long], [SINGLE]";
- LOGGER.info(imsg);
- graphMgmt.makePropertyKey(START_TS).dataType(Long.class)
- .cardinality(Cardinality.SINGLE).make();
- }
-
- if (graphMgmt.containsRelationType(END_TS)) {
- String dmsg = "PropertyKey [" + END_TS + "] already existed in the DB. ";
- LOGGER.debug(dmsg);
- } else if (!seenProps.containsKey(END_TS) ) {
- String imsg = " Creating PropertyKey: [" + END_TS + "], [Long], [SINGLE]";
- LOGGER.info(imsg);
- graphMgmt.makePropertyKey(END_TS).dataType(Long.class)
- .cardinality(Cardinality.SINGLE).make();
- }
-
- if (graphMgmt.containsRelationType(START_TX_ID)) {
- String dmsg = "PropertyKey [" + START_TX_ID + "] already existed in the DB. ";
- LOGGER.debug(dmsg);
- } else if (!seenProps.containsKey(START_TX_ID) ) {
- String imsg = " Creating PropertyKey: [" + START_TX_ID + "], [String], [SINGLE]";
- LOGGER.info(imsg);
- graphMgmt.makePropertyKey(START_TX_ID).dataType(String.class)
- .cardinality(Cardinality.SINGLE).make();
- }
+ makeNewProperty(graphMgmt, seenProps, String.class, END_SOT);
+ makeNewProperty(graphMgmt, seenProps, Long.class, START_TS);
+ makeNewProperty(graphMgmt, seenProps, Long.class, END_TS);
+ makeNewProperty(graphMgmt, seenProps, String.class, START_TX_ID);
+ makeNewProperty(graphMgmt, seenProps, String.class, END_TX_ID);
- if (graphMgmt.containsRelationType(END_TX_ID)) {
- String dmsg = "PropertyKey [" + END_TX_ID + "] already existed in the DB. ";
- LOGGER.debug(dmsg);
- } else if (!seenProps.containsKey(END_TX_ID) ) {
- String imsg = " Creating PropertyKey: [" + END_TX_ID + "], [String], [SINGLE]";
- LOGGER.info(imsg);
- graphMgmt.makePropertyKey(END_TX_ID).dataType(String.class)
- .cardinality(Cardinality.SINGLE).make();
- }
String imsg = "-- About to call graphMgmt commit";
LOGGER.info(imsg);
graphMgmt.commit();
if (backend != null) {
- LOGGER.info("Successfully loaded the schema to " + backend);
+ LOGGER.info("Successfully loaded the schema to {}", backend);
}
}
+ private static <T> void makeNewProperty(JanusGraphManagement graphMgmt,
+ Map<String, PropertyKey> seenProps,
+ Class<T> type,
+ String propertyName) {
+ if (graphMgmt.containsRelationType(propertyName)) {
+ LOGGER.debug("PropertyKey [{}] already existed in the DB.", propertyName);
+ } else if (!seenProps.containsKey(propertyName)) {
+ LOGGER.info("Creating PropertyKey: [{}], [{}], [{}]",
+ propertyName, type.getSimpleName(), Cardinality.SINGLE);
+ graphMgmt.makePropertyKey(propertyName).dataType(type).cardinality(Cardinality.SINGLE)
+ .make();
+ }
+ }
}
logger.info("-- loading schema into JanusGraph");
if ("true".equals(SpringContextAware.getApplicationContext().getEnvironment().getProperty("history.enabled", "false"))) {
- SchemaGenerator4Hist.loadSchemaIntoJanusGraph(graph, graphMgt, IN_MEMORY);
+ SchemaGenerator4Hist.loadSchemaIntoJanusGraph(graphMgt, IN_MEMORY);
} else {
SchemaGenerator.loadSchemaIntoJanusGraph(graphMgt, IN_MEMORY);
}
private static final long serialVersionUID = -5615651557821878103L;
+ private static final String AAI_MSG="AAI_3000";
public AAIUnmarshallingException() {
}
public AAIUnmarshallingException(String message) {
- super("AAI_3000", message);
+ super(AAI_MSG, message);
}
public AAIUnmarshallingException(Throwable cause) {
- super("AAI_3000", cause);
+ super(AAI_MSG, cause);
}
public AAIUnmarshallingException(String message, Throwable cause) {
- super("AAI_3000", cause, message);
+ super(AAI_MSG, cause, message);
}
}
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
import java.util.concurrent.ThreadPoolExecutor;
public class RestHandlerService {
- private static RestHandlerService single_instance = null;
+ private static RestHandlerService singleInstance = null;
public ThreadPoolExecutor executor;
- // private constructor restricted to this class itself
private RestHandlerService() {
executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(50);
}
* @return single instance of RestHandlerService
*/
public static RestHandlerService getInstance() {
- if (single_instance == null) {
- single_instance = new RestHandlerService();
+ if (singleInstance == null) {
+ singleInstance = new RestHandlerService();
}
- return single_instance;
+ return singleInstance;
}
}
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
public abstract class QueryEngine {
- final protected GraphTraversalSource g;
+ protected final GraphTraversalSource g;
protected double dbTimeMsecs = 0;
/**
public abstract List<Path> findCousinsAsPath(Vertex start);
public abstract double getDBTimeMsecs();
-
}
json.addProperty(prop.key(), gson.toJson(prop.value()));
} else {
// throw exception?
- return null;
+ return Optional.empty();
}
}
} else {
json.add(inner);
} else {
Optional<JsonObject> obj = this.getJsonFromVertex((Vertex)l, properties);
- json.add(obj.get());
+ if(obj.isPresent()) json.add(obj.get());
}
}
return Optional.of(json);
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.tinkerpop.gremlin.process.traversal.Path;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
import org.apache.tinkerpop.gremlin.structure.Vertex;
Logger logger = LoggerFactory.getLogger(MultiFormatMapper.class);
protected boolean isTree = false;
+ protected static final String PROPERTIES_KEY = "properties";
+ protected static final String NODE_TYPE_KEY = "node-type";
+
+ protected static final String RETURNED_EMPTY_JSONARRAY_MSG =
+ "Returned empty JsonArray - Could not populate nested json objects for wrapper: {}";
@Override
public Optional<JsonObject> formatObject(Object input)
if (ja.size() > 0) {
t.add("nodes", ja);
} else {
- logger.debug("Returned empty JsonArray - Could not populate nested json objects for wrapper: {}", nodeIdentifier);
+ logger.debug(RETURNED_EMPTY_JSONARRAY_MSG, nodeIdentifier);
}
return Optional.of(t);
t.add("results", ja);
return Optional.of(t);
} else {
- logger.debug("Returned empty JsonArray - Could not populate nested json objects for wrapper: {}", nodeIdentifier);
+ logger.debug(RETURNED_EMPTY_JSONARRAY_MSG, nodeIdentifier);
}
return Optional.empty();
if (ja.size() > 0) {
me.add(nodeIdentifier, ja);
} else {
- logger.debug("Returned empty JsonArray - Could not populate nested json objects for wrapper: {}", nodeIdentifier);
+ logger.debug(RETURNED_EMPTY_JSONARRAY_MSG, nodeIdentifier);
}
nodes.add(me);
}
if (properties == null)
return new HashMap<>();
- Map<String, Set<String>> filterPropertiesMap = new HashMap<>();
- for (String key : properties.keySet()) {
- if (!filterPropertiesMap.containsKey(key)) {
- Set<String> newSet = new HashSet<>();
- for (String currProperty : properties.get(key)) {
- currProperty = truncateApostrophes(currProperty);
- newSet.add(currProperty);
+ return properties.entrySet().stream()
+ .map(entry -> {
+ Set<String> newSet = entry.getValue().stream()
+ .map(this::truncateApostrophes)
+ .collect(Collectors.toSet());
+
+ return Pair.of(entry.getKey(), newSet);
}
- filterPropertiesMap.put(key, newSet);
- }
- }
- return filterPropertiesMap;
+ ).collect(Collectors.toMap(Pair::getKey, Pair::getValue));
}
/**
* @param filterPropertiesMap
* @return
*/
- protected JsonObject getPropertyFilteredObject(Optional<JsonObject> obj, Map<String, Set<String>> filterPropertiesMap) {
- if (filterPropertiesMap == null || filterPropertiesMap.isEmpty()) {
- return obj.get();
- }
- JsonObject jsonObj = obj.get();
- JsonObject result = new JsonObject();
- if (jsonObj != null) {
- String nodeType = "";
- JsonObject properties = null;
- // clone object
- for (Map.Entry<String, JsonElement> mapEntry : jsonObj.entrySet()) {
- String key = mapEntry.getKey(); JsonElement value = mapEntry.getValue();
-
- // also, check if payload has node-type and properties fields
- if (key.equals("node-type") && value != null) {
- nodeType = value.getAsString();
- } else if (key.equals("properties") && value != null && value.isJsonObject()) {
- properties = value.getAsJsonObject();
+ protected JsonObject getPropertyFilteredObject(Optional<JsonObject> obj,
+ Map<String, Set<String>> filterPropertiesMap) {
+ return obj.map(
+ jsonObj -> {
+ if (filterPropertiesMap == null || filterPropertiesMap.isEmpty()) {
+ return jsonObj;
+ } else {
+ ImmutableTriple<JsonObject, Optional<String>, Optional<JsonObject>> triple =
+ cloneObjectAndExtractNodeTypeAndProperties(jsonObj);
+
+ JsonObject result = triple.left;
+ Optional<String> nodeType = triple.middle;
+ Optional<JsonObject> properties = triple.right;
+
+ // Filter current object based on it containing fields: "node-type" and "properties"
+ if (nodeType.isPresent() && properties.isPresent()) {
+ filterByNodeTypeAndProperties(result, nodeType.get(), properties.get(), filterPropertiesMap);
+ } else {
+ // filter current object based on the: key - nodeType & value - JsonObject of nodes properties
+ filterByJsonObj(result, jsonObj, filterPropertiesMap);
+ }
+
+ return result;
}
- result.add(key, value);
}
+ ).orElseGet(JsonObject::new);
+ }
- // Filter current object based on it containing fields: "node-type" and "properties"
- if (!nodeType.isEmpty() && properties != null) {
- filterByNodeTypeAndProperties(result, nodeType, properties, filterPropertiesMap);
- } else {
- // filter current object based on the: key - nodeType & value - JsonObject of nodes properties
- filterByJsonObj(result, jsonObj, filterPropertiesMap);
+ private ImmutableTriple<JsonObject, Optional<String>, Optional<JsonObject>> cloneObjectAndExtractNodeTypeAndProperties(
+ JsonObject jsonObj) {
+ JsonObject result = new JsonObject();
+ Optional<String> nodeType = Optional.empty();
+ Optional<JsonObject> properties = Optional.empty();
+
+ // clone object
+ for (Map.Entry<String, JsonElement> mapEntry : jsonObj.entrySet()) {
+ String key = mapEntry.getKey();
+ JsonElement value = mapEntry.getValue();
+
+ // also, check if payload has node-type and properties fields
+ if (key.equals(NODE_TYPE_KEY) && value != null) {
+ nodeType = Optional.of(value.getAsString());
+ } else if (key.equals(PROPERTIES_KEY) && value != null && value.isJsonObject()) {
+ properties = Optional.of(value.getAsJsonObject());
}
+ result.add(key, value);
}
- return result;
+
+ return ImmutableTriple.of(result, nodeType, properties);
}
/**
filteredProperties.add(property, properties.get(property));
}
}
- result.remove("properties");
- result.add("properties", filteredProperties);
+ result.remove(PROPERTIES_KEY);
+ result.add(PROPERTIES_KEY, filteredProperties);
}
return result;
}
}
for (Map.Entry<String, JsonElement> mapEntry : jsonObj.entrySet()) {
- String key = mapEntry.getKey(); JsonElement value = mapEntry.getValue();
+ String key = mapEntry.getKey();
+ JsonElement value = mapEntry.getValue();
JsonObject filteredProperties = new JsonObject();
if (value != null && value.isJsonObject() && filterPropertiesMap.containsKey(key)) {
JsonObject joProperties = value.getAsJsonObject();
* @param filterPropertiesMap
* @return
*/
- protected JsonObject filterProperties(Optional<JsonObject> properties, String nodeType, Map<String, Set<String>> filterPropertiesMap) {
- if (filterPropertiesMap == null || filterPropertiesMap.isEmpty()) {
- return properties.get();
- }
+ protected JsonObject filterProperties(Optional<JsonObject> properties, String nodeType,
+ Map<String, Set<String>> filterPropertiesMap) {
+ return properties.map(jo -> {
+ if (filterPropertiesMap == null || filterPropertiesMap.isEmpty()) {
+ return properties.get();
+ }
- JsonObject jo = properties.get();
- JsonObject result = new JsonObject();
- if (jo != null) {
+ JsonObject result = new JsonObject();
// clone the object
for (Map.Entry<String, JsonElement> mapEntry : jo.entrySet()) {
String key = mapEntry.getKey();
}
}
}
- }
- return result;
+ return result;
+ }).orElseGet(JsonObject::new);
}
@Override
ctx = SSLContext.getInstance("TLSv1.2");
KeyManagerFactory kmf = null;
- try {
+
+ try(FileInputStream fin = new FileInputStream(keystorePath)) {
kmf = KeyManagerFactory.getInstance("SunX509");
- FileInputStream fin = new FileInputStream(keystorePath);
KeyStore ks = KeyStore.getInstance("PKCS12");
char[] pwd = keystorePassword.toCharArray();
ks.load(fin, pwd);
import org.junit.Test;
import org.onap.aai.AAISetup;
import org.onap.aai.setup.SchemaVersion;
+import org.springframework.test.annotation.DirtiesContext;
import java.util.List;
import java.util.Map;
import java.util.Properties;
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
public class ListEndpointsTest extends AAISetup {
private Properties properties;
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
}
@Test
- public void getRealtimeInstanceConnectionName() throws Exception {
+ public void getRealtimeInstanceConnectionName() {
JanusGraphManagement graphMgt = AAIGraph.getInstance().getGraph().openManagement();
String connectionInstanceName =
@Ignore("Need to create schema specific to the test")
@Test
- public void checkIndexOfAliasedIndexedProps() throws Exception {
+ public void checkIndexOfAliasedIndexedProps() {
Set<String> aliasedIndexedProps = getAliasedIndexedProps();
JanusGraphManagement graphMgt = AAIGraph.getInstance().getGraph().openManagement();
for (String aliasedIndexedProp : aliasedIndexedProps) {
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
* as these keys are generated in a couple places, I made a class to contain that logic
*/
public class HbaseSaltPrefixer {
- private int NUM_REGION_BUCKETS = 3; // the number of hbase region servers per cluster
+ // the number of hbase region servers per cluster
+ private static int NUM_REGION_BUCKETS = 3;
private static class SingletonHolder {
private static final HbaseSaltPrefixer INSTANCE = new HbaseSaltPrefixer();
}
- /**
- * Instantiates a new hbase salt prefixer.
- */
private HbaseSaltPrefixer() {
}
- /**
- * Gets the single instance of HbaseSaltPrefixer.
- *
- * @return single instance of HbaseSaltPrefixer
- */
public static HbaseSaltPrefixer getInstance() {
return SingletonHolder.INSTANCE;
}
- /**
- * Prepend salt.
- *
- * @param key the key
- * @return the string
- */
public String prependSalt(String key) {
int salt = Math.abs(key.hashCode()) % NUM_REGION_BUCKETS;
return salt + "-" + key;
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
LoggingContext.elapsedTime(300, TimeUnit.MILLISECONDS);
assertEquals(MDC.get(LoggingContext.LoggingField.ELAPSED_TIME.toString()), "300");
LoggingContext.init();
- assertTrue(MDC.get(LoggingContext.LoggingField.ELAPSED_TIME.toString()) == null);
+ assertNull(MDC.get(LoggingContext.LoggingField.ELAPSED_TIME.toString()));
}
@Test
public void stopWatchTest() {
assertEquals(testServiceName, MDC.get(LoggingContext.LoggingField.SERVICE_NAME.toString()));
LoggingContext.clear();
- assertTrue(MDC.get(LoggingContext.LoggingField.SERVICE_NAME.toString()) == null);
+ assertNull(MDC.get(LoggingContext.LoggingField.SERVICE_NAME.toString()));
}
assertEquals(testServiceName, MDC.get(LoggingContext.LoggingField.SERVICE_NAME.toString()));
LoggingContext.remove(LoggingContext.LoggingField.SERVICE_NAME.toString());
- assertTrue(MDC.get(LoggingContext.LoggingField.SERVICE_NAME.toString()) == null);
+ assertNull(MDC.get(LoggingContext.LoggingField.SERVICE_NAME.toString()));
}
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
* 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
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
* 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.
public class ClientType {
public static final String AAI = "aai-rest-client";
+
+ private ClientType() {
+ }
}
package org.onap.aai.schemaif;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.onap.aai.schemaif.definitions.EdgeSchema;
import org.onap.aai.schemaif.definitions.VertexSchema;
+import java.util.Map;
+import java.util.Set;
+
public interface SchemaProvider {
-
+
/**
* Load the schema into memory
*/
- public void loadSchema() throws SchemaProviderException;
-
+ void loadSchema() throws SchemaProviderException;
+
/**
* Get the identifier for the more recent version of the schema
*
* @return The schema version identifier
*/
- public String getLatestSchemaVersion() throws SchemaProviderException;
-
+ String getLatestSchemaVersion() throws SchemaProviderException;
+
/**
* Get the schema definition for a vertex
*
* @param vertexName - Name of the vertex
* @param schemaVersion - Version of the schema to use
- *
+ *
* @return The vertex schema definition
*/
- public VertexSchema getVertexSchema(String vertexName, String schemaVersion) throws SchemaProviderException;
-
+ VertexSchema getVertexSchema(String vertexName, String schemaVersion) throws SchemaProviderException;
+
/**
* Get the schema definition for an edge
*
* @param edgeType - Type of the edge
* @param sourceVertex - The source vertex for the edge
* @param targetVertex - The target vertex for the edge
- * @param schemaVersion - Version of the schema to use
- *
+ * @param version - Version of the schema to use
+ *
* @return The edge schema definition
*/
- public EdgeSchema getEdgeSchema(String edgeType, String sourceVertex, String targetVertex, String version) throws SchemaProviderException;
+ EdgeSchema getEdgeSchema(String edgeType, String sourceVertex, String targetVertex, String version) throws SchemaProviderException;
/**
* Get the list of edge definitions which are adjacent to the given vertex
*
* @param vertexType - Type of the vertex
- * @param schemaVersion - Version of the schema to use
- *
+ * @param version - Version of the schema to use
+ *
* @return The list of edge schema definitions
*/
- public Set<EdgeSchema> getAdjacentEdgeSchema(String vertexType, String version) throws SchemaProviderException;
-
+ Set<EdgeSchema> getAdjacentEdgeSchema(String vertexType, String version) throws SchemaProviderException;
+
/**
* Get the list of edge definitions which are valid for the given source and target
*
* @param sourceType - Type of the source vertex
* @param targetType - Type of the target vertex
- * @param schemaVersion - Version of the schema to use
- *
+ * @param version - Version of the schema to use
+ *
* @return The list of edge schema definitions
*/
- public Set<EdgeSchema> getEdgeSchemaForSourceTarget(String sourceType, String targetType, String version) throws SchemaProviderException;
+ Set<EdgeSchema> getEdgeSchemaForSourceTarget(String sourceType, String targetType, String version) throws SchemaProviderException;
/**
* Get vertex map for a schema version
*
* @param schemaVersion - Version of the schema to use
- *
+ *
* @return The list of vertex types
*/
- public Map<String, VertexSchema> getVertexMap(String schemaVersion) throws SchemaProviderException;
-
+ Map<String, VertexSchema> getVertexMap(String schemaVersion) throws SchemaProviderException;
}
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
package org.onap.aai.schemaif.definitions.types;
-import org.onap.aai.schemaif.SchemaProviderException;
-
public abstract class DataType {
public enum Type {
- STRING,
+ STRING,
BOOL,
INT,
LONG,
MAP,
COMPLEX
}
-
- private Type type;
-
+
+ private final Type type;
+
public DataType(Type type) {
this.type = type;
}
public Type getType() {
return type;
}
-
+
public abstract Object validateValue(String value);
-
+
public String toString() {
return getType().toString();
}
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
*/
package org.onap.aai.schemaif.json;
-import org.onap.aai.schemaif.SchemaProviderException;
-import org.onap.aai.schemaif.json.definitions.JsonSchema;
-
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName;
+import org.onap.aai.schemaif.SchemaProviderException;
+import org.onap.aai.schemaif.json.definitions.JsonSchema;
public class SchemaServiceResponse {
public static final String SCHEMA_TYPE_OXM = "oxm";
public static final String SCHEMA_TYPE_JSON = "json";
-
+
private static final Gson gson = new GsonBuilder().create();
@SerializedName("schema-version")
private String version;
-
+
@SerializedName("schema-content")
private JsonSchema data;
-
+
public String getVersion() {
return version;
}
if (json == null || json.isEmpty()) {
throw new SchemaProviderException("Empty schema-service response");
}
-
+
return gson.fromJson(json, SchemaServiceResponse.class);
} catch (Exception ex) {
throw new SchemaProviderException("Invalid response from schema service: " + ex.getMessage());
}
}
-
}
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
OxmEdgeRulesLoader.loadModels();
OxmSchemaLoader.loadModels();
}
-
+
@Override
public String getLatestSchemaVersion() throws SchemaProviderException {
return OxmSchemaLoader.getLatestVersion();
if (edgeRule == null) {
return null;
}
-
+
FromOxmEdgeSchema es = new FromOxmEdgeSchema();
es.fromEdgeRule(edgeRule);
-
+
return es;
}
@Override
public Set<EdgeSchema> getAdjacentEdgeSchema(String vertexType, String version) throws SchemaProviderException {
RelationshipSchema relSchema = OxmEdgeRulesLoader.getSchemaForVersion(version);
- Set<EdgeSchema> edges = new HashSet<EdgeSchema>();
+ Set<EdgeSchema> edges = new HashSet<>();
List<EdgeRule> rules = relSchema.lookupAdjacentEdges(vertexType);
-
+
for (EdgeRule rule : rules) {
FromOxmEdgeSchema es = new FromOxmEdgeSchema();
es.fromEdgeRule(rule);
edges.add(es);
}
-
+
return edges;
}
-
+
@Override
public Set<EdgeSchema> getEdgeSchemaForSourceTarget(String sourceType, String targetType, String version) throws SchemaProviderException {
RelationshipSchema relSchema = OxmEdgeRulesLoader.getSchemaForVersion(version);
- Set<EdgeSchema> edges = new HashSet<EdgeSchema>();
+ Set<EdgeSchema> edges = new HashSet<>();
Set<String> relTypes = relSchema.getValidRelationTypes(sourceType, targetType);
-
+
for (String type : relTypes) {
EdgeSchema edgeSchema = getEdgeSchema(type, sourceType, targetType, version);
if (edgeSchema != null) {
edges.add(edgeSchema);
}
}
-
+
return edges;
}
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
package org.onap.aai.nodes;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.*;
-
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-
-import javax.xml.bind.SchemaOutputResolver;
-import javax.xml.transform.*;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
import org.junit.Rule;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.onap.aai.config.NodesConfiguration;
-import org.onap.aai.restclient.MockProvider;
import org.onap.aai.setup.SchemaVersion;
import org.onap.aai.testutils.TestUtilConfigTranslator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.w3c.dom.Document;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+
@RunWith(SpringRunner.class)
@TestPropertySource(
properties = {
@Autowired
NodeIngestor nodeIngestor;
- public static void printDocument(Document doc, OutputStream out) throws IOException, TransformerException {
+ public static void printDocument(Document doc, OutputStream out) throws TransformerException {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
- transformer.transform(new DOMSource(doc), new StreamResult(new OutputStreamWriter(out, "UTF-8")));
+ transformer.transform(new DOMSource(doc), new StreamResult(new OutputStreamWriter(out, UTF_8)));
}
@Test
DynamicEntity foo10 = ctx10.newDynamicEntity("Foo");
foo10.set("fooId", "bar");
- assertTrue("bar".equals(foo10.get("fooId")));
+ assertEquals("bar", foo10.get("fooId"));
// should work bc Bar is valid in test_business_v10 schema
DynamicEntity bar10 = ctx10.newDynamicEntity("Bar");
bar10.set("barId", "bar2");
- assertTrue("bar2".equals(bar10.get("barId")));
+ assertEquals("bar2", bar10.get("barId"));
XSDOutputResolver outputResolver10 = new XSDOutputResolver();
ctx10.generateSchema(outputResolver10);
// should work bc Foo.quantity is valid in test_network_v11 schema
DynamicEntity foo11 = ctx11.newDynamicEntity("Foo");
foo11.set("quantity", "12");
- assertTrue("12".equals(foo11.get("quantity")));
+ assertEquals("12", foo11.get("quantity"));
DynamicEntity quux11 = ctx11.newDynamicEntity("Quux");
quux11.set("qManagerName", "some guy");
- assertTrue("some guy".equals(quux11.get("qManagerName")));
+ assertEquals("some guy", quux11.get("qManagerName"));
XSDOutputResolver outputResolver11 = new XSDOutputResolver();
ctx11.generateSchema(outputResolver11);
@Test
public void testGetVersionFromClassName() {
assertEquals(nodeIngestor.getVersionFromClassName("inventory.aai.onap.org.v13.Evc"), new SchemaVersion("v13"));
-
}
@Test
public void testGetVersionFromClassNameNull() {
assertEquals(nodeIngestor.getVersionFromClassName("blah"), new SchemaVersion("v15"));
-
}
@Test
public void testGetObjectsInVersion() {
assertEquals(nodeIngestor.getObjectsInVersion(new SchemaVersion("v13")).size(), 148);
-
}
@Test
assertThat("OXM:\n" + expected, expected, is(content));
}
- private class XSDOutputResolver extends SchemaOutputResolver {
+ private static class XSDOutputResolver extends SchemaOutputResolver {
@Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
-/**
+/*
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
package org.onap.aai.nodes;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.*;
-
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-
-import javax.xml.bind.SchemaOutputResolver;
-import javax.xml.transform.*;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
import org.junit.Rule;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.w3c.dom.Document;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+
@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource(
properties = {
DynamicEntity foo10 = ctx10.newDynamicEntity("Foo");
foo10.set("fooId", "bar");
- assertTrue("bar".equals(foo10.get("fooId")));
+ assertEquals("bar", foo10.get("fooId"));
// should work bc Bar is valid in test_business_v10 schema
DynamicEntity bar10 = ctx10.newDynamicEntity("Bar");
bar10.set("barId", "bar2");
- assertTrue("bar2".equals(bar10.get("barId")));
+ assertEquals("bar2", bar10.get("barId"));
XSDOutputResolver outputResolver10 = new XSDOutputResolver();
ctx10.generateSchema(outputResolver10);
// should work bc Foo.quantity is valid in test_network_v11 schema
DynamicEntity foo11 = ctx11.newDynamicEntity("Foo");
foo11.set("quantity", "12");
- assertTrue("12".equals(foo11.get("quantity")));
+ assertEquals("12", foo11.get("quantity"));
DynamicEntity quux11 = ctx11.newDynamicEntity("Quux");
quux11.set("qManagerName", "some guy");
- assertTrue("some guy".equals(quux11.get("qManagerName")));
+ assertEquals("some guy", quux11.get("qManagerName"));
XSDOutputResolver outputResolver11 = new XSDOutputResolver();
ctx11.generateSchema(outputResolver11);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
- transformer.transform(new DOMSource(doc), new StreamResult(new OutputStreamWriter(out, "UTF-8")));
+ transformer.transform(new DOMSource(doc), new StreamResult(new OutputStreamWriter(out, UTF_8)));
}
- private class XSDOutputResolver extends SchemaOutputResolver {
+ private static class XSDOutputResolver extends SchemaOutputResolver {
@Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
-
- // create new file
- // create stream result
File temp = File.createTempFile("schema", ".xsd");
StreamResult result = new StreamResult(temp);
System.out.println("Schema file: " + temp.getAbsolutePath());
- // set system id
result.setSystemId(temp.toURI().toURL().toString());
- // return result
return result;
}
}
With the high volume and variety of data, AAI must be prepared to answer many types of queries; real-time search to quickly retrieve specific items from an ocean of data, relationships to determine impacts and consequences, aggregations and counts to explore availability and consumption, validation and integrity to establish whether systems are acting on good information, history and provenance to reconstruct the current view and its context, and enrichment out to legacy systems to examine the low-level details of the network and virtual assets.
.. image:: images/aai_in_onap.png
+
+AAI Components
+^^^^^^^^^^^^^^
+
+.. image:: images/aai_components.png
+
+ESR
+"""
+Applications for management of external systems.
+
+================== ===
+**aai/esr-gui** External system management ui. UI for esr-server.
+**aai/esr-server** ESR backend, mainly include the function of external system reachable check and data pretreatment.
+================== ===
+
+Input abstraction
+"""""""""""""""""
+Applications that serve as entry points to A&AI.
+
+==================== ===
+**aai/model-loader** Obtains SDC artifacts and loads them into the A&AI Resources service for storage.
+**aai/sparky-be** AAI user interface back end.
+**aai/sparky-fe** AAI user interface front end.
+==================== ===
+
+Query abstraction
+"""""""""""""""""
+Query abstraction point for clients that routes AAI queries and event data.
+
+=================== ===
+**aai/data-router** AAI Microservice used to route AAI queries and event data to correct storage engine. Serves as a query abstraction point for clients, as well as a gateway.
+=================== ===
+
+Data management
+"""""""""""""""
+Microservices that facilitate data management of AAI objects.
+
+============================ ===
+**aai/babel** AAI Microservice to generate AAI model XML from SDC TOSCA CSAR artifacts.
+**aai/cacher** Cacher is a generic service that can be used to snapshot json responses, force sync them, sync them periodically, or update them by consuming dmaap events.
+**aai/chameleon** (deprecated) Abstraction service for historical database.
+**aai/champ** Abstraction from underlying graph storage systems that A&AI would interface with.
+**aai/gizmo** (deprecated) CRUD Rest API endpoint for resources and relationships, delivering atomic interactions with the graph for improved scalability.
+**aai/resources** AAI Resources Micro Service providing CRUD REST APIs for inventory resources. This microservice provides the main path for updating and searching the graph - java-types defined in the OXM file for each version of the API define the REST endpoints - for example, the java-type "CloudRegion" in aai-common/aai-schema/src/main/resources/oxm/aai_oxm_v11.xml maps to /aai/v11/cloud-infrastructure/cloud-regions/cloud-region.
+**aai/search-data-service** Abstraction layer for searchengine, supporting queries and updates. Currently supports Elasticsearch, but has also been design with Solr support in mind.
+**aai/spike** (deprecated) Microservice used to generate events describing changes to the graph data.
+**aai/tabular-data-service** (deprecated) Microservice which serves as an abstraction layer to a tabular data store.
+**aai/validation** Microservice used to invoke validation mechanism .
+============================ ===
+
+Graph services
+""""""""""""""
+Set of components, which store, provide or display schemas.
+
+====================== ===
+**aai/graphadmin** Microservice with various functions for graph management.
+**aai/graphgraph** Microservice used to provide view of AAI model, schema and edge rules.
+**aai/schema-service** Application holds and provides specified schema versions.
+**aai/traversal** AAI Traversal Micro Service providing REST APIs for traversal/search of inventory resources. Custom queries (gremin-style traversals) model based queries (which use a model either manually created or loaded from SDC models) and named-queries (traversals which ignore edge labels and direction and just link together objects of given node types from a starting node).
+====================== ===
+
+Libraries
+"""""""""
+Libraries don't run as standalone applications. They contain general functionality, which may be imported and used in other modules.
+
+======================= ===
+**aai/aai-common** This holds the model, annotations and common modules used across the Resources and Traversal micro services. aai/aai-common creates artifacts like aai-core, aai-schema and aai-annotations, which are used by the rest of the microservices and libraries.
+**aai/event-client** Event bus client library.
+**aai/logging-service** AAI common logging library.
+**aai/rest-client** Library for making REST calls.
+**aai/router-core** Library containing the core camel components for the data router.
+======================= ===
+
+Configuration repositories
+""""""""""""""""""""""""""
+Contain several repositories that include various configuration.
+
+=================== ===
+**aai/aai-data** (deprecated) AAI Chef environment files.
+**aai/aai-config** (deprecated) AAI Chef cookbooks.
+**aai/aai-service** (deprecated) AAI REST based services.
+**aai/oom**
+**aai/test-config** Repository containing test configuration for use in continuous integration.
+=================== ===