From df8e8f551fd6df1b983f009ca988ab1518176e29 Mon Sep 17 00:00:00 2001 From: ur326r Date: Mon, 14 Aug 2017 13:56:13 -0400 Subject: [PATCH] [AAI-168 Amsterdam] Check in source Change-Id: I9b7169c5cd346254990118df15792454f9455f95 Signed-off-by: ur326r --- .../engines/TransactionalGraphEngine.java | 7 +- .../aai/serialization/queryformats/Format.java | 3 +- .../serialization/queryformats/FormatFactory.java | 35 +++- .../aai/serialization/queryformats/RawFormat.java | 189 +++++++++++++++++++++ .../aai/serialization/queryformats/Resource.java | 34 +++- .../serialization/queryformats/SimpleFormat.java | 107 ++++-------- .../exceptions/QueryParamInjectionException.java | 40 +++++ .../serialization/queryformats/params/Depth.java | 28 +++ .../serialization/queryformats/params/Inject.java | 34 ++++ .../queryformats/params/NodesOnly.java | 28 +++ .../serialization/queryformats/params/Setter.java | 36 ++++ .../queryformats/utils/QueryParamInjector.java | 84 +++++++++ .../queryformats/SimpleFormatTest.java | 177 +++++++++++++++++++ .../queryformats/utils/QueryParamInjectorTest.java | 59 +++++++ 14 files changed, 769 insertions(+), 92 deletions(-) create mode 100644 aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/RawFormat.java create mode 100644 aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/exceptions/QueryParamInjectionException.java create mode 100644 aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Depth.java create mode 100644 aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Inject.java create mode 100644 aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/NodesOnly.java create mode 100644 aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Setter.java create mode 100644 aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/utils/QueryParamInjector.java create mode 100644 aai-core/src/test/java/org/openecomp/aai/serialization/queryformats/SimpleFormatTest.java create mode 100644 aai-core/src/test/java/org/openecomp/aai/serialization/queryformats/utils/QueryParamInjectorTest.java diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/engines/TransactionalGraphEngine.java b/aai-core/src/main/java/org/openecomp/aai/serialization/engines/TransactionalGraphEngine.java index ffe866ed..21d36725 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/engines/TransactionalGraphEngine.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/engines/TransactionalGraphEngine.java @@ -148,11 +148,11 @@ public abstract class TransactionalGraphEngine { public QueryBuilder getQueryBuilder(QueryStyle style) { return getQueryBuilder(style, this.loader); } - + public QueryBuilder getQueryBuilder(Loader loader) { return getQueryBuilder(this.style, loader); } - + public QueryBuilder getQueryBuilder(QueryStyle style, Loader loader) { if (style.equals(QueryStyle.GREMLIN_TRAVERSAL)) { return new GremlinTraversal<>(loader, this.asAdmin().getTraversalSource()); @@ -180,7 +180,7 @@ public abstract class TransactionalGraphEngine { public QueryBuilder getQueryBuilder(Loader loader, Vertex start) { return getQueryBuilder(this.style, loader, start); } - + public QueryBuilder getQueryBuilder(QueryStyle style, Loader loader, Vertex start) { if (style.equals(QueryStyle.GREMLIN_TRAVERSAL)) { return new GremlinTraversal<>(loader, this.asAdmin().getTraversalSource(), start); @@ -195,7 +195,6 @@ public abstract class TransactionalGraphEngine { } return queryBuilder; } - public Graph startTransaction() { if (this.tx() == null) { this.currentTx = this.getGraph().newTransaction(); diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/Format.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/Format.java index 90aa3855..0505f626 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/Format.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/Format.java @@ -25,5 +25,6 @@ public enum Format { pathed, id, resource, simple, resource_and_url, - console + console, + raw } diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/FormatFactory.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/FormatFactory.java index 92af377d..031e2a32 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/FormatFactory.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/FormatFactory.java @@ -20,9 +20,14 @@ package org.openecomp.aai.serialization.queryformats; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; + import org.openecomp.aai.exceptions.AAIException; import org.openecomp.aai.introspection.Loader; import org.openecomp.aai.serialization.db.DBSerializer; +import org.openecomp.aai.serialization.queryformats.exceptions.QueryParamInjectionException; +import org.openecomp.aai.serialization.queryformats.utils.QueryParamInjector; import org.openecomp.aai.serialization.queryformats.utils.UrlBuilder; public class FormatFactory { @@ -30,43 +35,59 @@ public class FormatFactory { private final Loader loader; private final DBSerializer serializer; private final UrlBuilder urlBuilder; + private final QueryParamInjector injector; public FormatFactory (Loader loader, DBSerializer serializer) throws AAIException { this.loader = loader; this.serializer = serializer; this.urlBuilder = new UrlBuilder(loader.getVersion(), serializer); + this.injector = QueryParamInjector.getInstance(); } public Formatter get(Format format) throws AAIException { + return get(format, new MultivaluedHashMap()); + } + + public Formatter get(Format format, MultivaluedMap params) throws AAIException { Formatter formattter = null; switch (format) { case graphson : - formattter = new Formatter(new GraphSON()); + formattter = new Formatter(inject(new GraphSON(), params)); break; case pathed : - formattter = new Formatter(new PathedURL(loader, urlBuilder)); + formattter = new Formatter(inject(new PathedURL(loader, urlBuilder), params)); break; case id : - formattter = new Formatter(new IdURL(loader, urlBuilder)); + formattter = new Formatter(inject(new IdURL(loader, urlBuilder), params)); break; case resource : - formattter = new Formatter(new Resource.Builder(loader, serializer, urlBuilder).build()); + formattter = new Formatter(inject(new Resource.Builder(loader, serializer, urlBuilder), params).build()); break; case resource_and_url : - formattter = new Formatter(new Resource.Builder(loader, serializer, urlBuilder).includeUrl().build()); + formattter = new Formatter(inject(new Resource.Builder(loader, serializer, urlBuilder).includeUrl(), params).build()); + break; + case raw : + formattter = new Formatter(inject(new RawFormat.Builder(loader, serializer, urlBuilder), params).build()); break; case simple : - formattter = new Formatter(new SimpleFormat(urlBuilder)); + formattter = new Formatter(inject(new RawFormat.Builder(loader, serializer, urlBuilder).depth(0).modelDriven(), params).build()); break; case console : - formattter = new Formatter(new Console()); + formattter = new Formatter(inject(new Console(), params)); break; default : break; + } return formattter; } + private T inject (T obj, MultivaluedMap params) throws QueryParamInjectionException { + + injector.injectParams(obj, params); + return obj; + } + } diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/RawFormat.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/RawFormat.java new file mode 100644 index 00000000..070e22f4 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/RawFormat.java @@ -0,0 +1,189 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.openecomp.aai.serialization.queryformats; + +import java.util.Iterator; +import java.util.List; + +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.openecomp.aai.db.props.AAIProperties; +import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.serialization.db.DBSerializer; +import org.openecomp.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.openecomp.aai.serialization.queryformats.params.Depth; +import org.openecomp.aai.serialization.queryformats.params.NodesOnly; +import org.openecomp.aai.serialization.queryformats.utils.UrlBuilder; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + + +public class RawFormat implements FormatMapper { + protected JsonParser parser = new JsonParser(); + protected final DBSerializer serializer; + protected final Loader loader; + protected final UrlBuilder urlBuilder; + protected final int depth; + protected final boolean nodesOnly; + protected RawFormat(Builder builder) { + this.urlBuilder = builder.getUrlBuilder(); + this.loader = builder.getLoader(); + this.serializer = builder.getSerializer(); + this.depth = builder.getDepth(); + this.nodesOnly = builder.isNodesOnly(); + } + + @Override + public JsonObject formatObject(Object input) throws AAIFormatVertexException { + Vertex v = (Vertex)input; + JsonObject json = new JsonObject(); + json.addProperty("id", v.id().toString()); + json.addProperty("node-type", v.value(AAIProperties.NODE_TYPE)); + json.addProperty("url", this.urlBuilder.pathed(v)); + json.add("properties", this.createPropertiesObject(v)); + if (!nodesOnly) { + json.add("related-to", this.createRelationshipObject(v)); + } + return json; + } + + @Override + public int parallelThreshold() { + return 100; + } + + + public JsonObject createPropertiesObject(Vertex v) throws AAIFormatVertexException { + JsonObject json = new JsonObject(); + Iterator> iter = v.properties(); + + while (iter.hasNext()) { + VertexProperty prop = iter.next(); + if (prop.value() instanceof String) { + json.addProperty(prop.key(), (String)prop.value()); + } else if (prop.value() instanceof Boolean) { + json.addProperty(prop.key(), (Boolean)prop.value()); + } else if (prop.value() instanceof Number) { + json.addProperty(prop.key(), (Number)prop.value()); + } else if (prop.value() instanceof List) { + Gson gson = new Gson(); + String list = gson.toJson(prop.value()); + + json.addProperty(prop.key(), list); + } else { + //throw exception? + return null; + } + } + + return json; + } + protected JsonArray createRelationshipObject(Vertex v) throws AAIFormatVertexException { + JsonArray jarray = new JsonArray(); + Iterator iter = v.vertices(Direction.BOTH); + + while (iter.hasNext()) { + Vertex related = iter.next(); + + JsonObject json = new JsonObject(); + json.addProperty("id", related.id().toString()); + json.addProperty("node-type", related.value(AAIProperties.NODE_TYPE)); + json.addProperty("url", this.urlBuilder.pathed(related)); + jarray.add(json); + } + + return jarray; + } + + public static class Builder implements NodesOnly, Depth { + + protected final Loader loader; + protected final DBSerializer serializer; + protected final UrlBuilder urlBuilder; + protected boolean includeUrl = false; + protected boolean nodesOnly = false; + protected int depth = 1; + protected boolean modelDriven = false; + public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { + this.loader = loader; + this.serializer = serializer; + this.urlBuilder = urlBuilder; + } + + protected Loader getLoader() { + return this.loader; + } + + protected DBSerializer getSerializer() { + return this.serializer; + } + + protected UrlBuilder getUrlBuilder() { + return this.urlBuilder; + } + + public Builder includeUrl() { + this.includeUrl = true; + return this; + } + + public Builder nodesOnly(Boolean nodesOnly) { + this.nodesOnly = nodesOnly; + return this; + } + public boolean isNodesOnly() { + return this.nodesOnly; + } + + public Builder depth(Integer depth) { + this.depth = depth; + return this; + } + + public int getDepth() { + return this.depth; + } + + public boolean isIncludeUrl() { + return this.includeUrl; + } + + public Builder modelDriven() { + this.modelDriven = true; + return this; + } + + public boolean getModelDriven() { + return this.modelDriven; + } + public RawFormat build() { + if (modelDriven) { + return new SimpleFormat(this); + } else { + return new RawFormat(this); + } + } + } +} diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/Resource.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/Resource.java index c30b871b..9a090a4b 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/Resource.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/Resource.java @@ -25,7 +25,6 @@ import java.util.ArrayList; import java.util.List; import org.apache.tinkerpop.gremlin.structure.Vertex; - import org.openecomp.aai.db.props.AAIProperties; import org.openecomp.aai.exceptions.AAIException; import org.openecomp.aai.introspection.Introspector; @@ -33,7 +32,10 @@ import org.openecomp.aai.introspection.Loader; import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; import org.openecomp.aai.serialization.db.DBSerializer; import org.openecomp.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.openecomp.aai.serialization.queryformats.params.Depth; +import org.openecomp.aai.serialization.queryformats.params.NodesOnly; import org.openecomp.aai.serialization.queryformats.utils.UrlBuilder; + import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -44,13 +46,16 @@ public class Resource implements FormatMapper { private final JsonParser parser; private final UrlBuilder urlBuilder; private final boolean includeUrl; - + private final boolean nodesOnly; + private final int depth; private Resource (Builder builder) { this.parser = new JsonParser(); this.loader = builder.getLoader(); this.serializer = builder.getSerializer(); this.urlBuilder = builder.getUrlBuilder(); this.includeUrl = builder.isIncludeUrl(); + this.nodesOnly = builder.isNodesOnly(); + this.depth = builder.getDepth(); } @Override @@ -79,7 +84,7 @@ public class Resource implements FormatMapper { wrapper.add(v); try { - getSerializer().dbToObject(wrapper, obj, 1, false, "false"); + getSerializer().dbToObject(wrapper, obj, this.depth, this.nodesOnly, "false"); } catch (AAIException | UnsupportedEncodingException e) { throw new AAIFormatVertexException("Failed to format vertex - error while serializing: " + e.getMessage(), e); } @@ -101,13 +106,14 @@ public class Resource implements FormatMapper { private DBSerializer getSerializer() { return serializer; } private JsonParser getParser() { return parser; } - public static class Builder { + public static class Builder implements NodesOnly, Depth { private final Loader loader; private final DBSerializer serializer; private final UrlBuilder urlBuilder; private boolean includeUrl = false; - + private boolean nodesOnly = false; + private int depth = 1; public Builder(Loader loader, DBSerializer serializer, UrlBuilder urlBuilder) { this.loader = loader; this.serializer = serializer; @@ -130,8 +136,22 @@ public class Resource implements FormatMapper { this.includeUrl = true; return this; } - - protected boolean isIncludeUrl() { + + public Builder nodesOnly(Boolean nodesOnly) { + this.nodesOnly = nodesOnly; + return this; + } + public boolean isNodesOnly() { + return this.nodesOnly; + } + public Builder depth(Integer depth) { + this.depth = depth; + return this; + } + public int getDepth() { + return this.depth; + } + public boolean isIncludeUrl() { return this.includeUrl; } diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/SimpleFormat.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/SimpleFormat.java index 649164c5..c14f9b79 100644 --- a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/SimpleFormat.java +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/SimpleFormat.java @@ -20,95 +20,56 @@ package org.openecomp.aai.serialization.queryformats; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; import java.util.List; -import java.util.Set; -import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; - import org.openecomp.aai.db.props.AAIProperties; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.introspection.Introspector; +import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; import org.openecomp.aai.serialization.queryformats.exceptions.AAIFormatVertexException; -import org.openecomp.aai.serialization.queryformats.utils.UrlBuilder; -import com.google.gson.Gson; -import com.google.gson.JsonArray; + import com.google.gson.JsonObject; -public class SimpleFormat implements FormatMapper { +public class SimpleFormat extends RawFormat { - private final UrlBuilder urlBuilder; - private final Set blacklist; - private final Collection props = Arrays.asList(AAIProperties.AAI_URI, AAIProperties.NODE_TYPE); - public SimpleFormat(UrlBuilder urlBuilder) { - this.urlBuilder = urlBuilder; - this.blacklist = new HashSet<>(); - blacklist.addAll(props); - } + + protected SimpleFormat(Builder builder) { + super(builder); - @Override - public JsonObject formatObject(Object input) throws AAIFormatVertexException { - Vertex v = (Vertex)input; - JsonObject json = new JsonObject(); - json.addProperty("id", v.id().toString()); - json.addProperty("node-type", v.value(AAIProperties.NODE_TYPE)); - json.addProperty("url", this.urlBuilder.pathed(v)); - json.add("properties", this.createPropertiesObject(v)); - json.add("related-to", this.createRelationshipObject(v)); - - return json; } - + @Override public int parallelThreshold() { - return 100; + return 20; } - private JsonObject createPropertiesObject(Vertex v) { - JsonObject json = new JsonObject(); - Iterator> iter = v.properties(); - - while (iter.hasNext()) { - VertexProperty prop = iter.next(); - if (!blacklist.contains(prop.key())) { - if (prop.value() instanceof String) { - json.addProperty(prop.key(), (String)prop.value()); - } else if (prop.value() instanceof Boolean) { - json.addProperty(prop.key(), (Boolean)prop.value()); - } else if (prop.value() instanceof Number) { - json.addProperty(prop.key(), (Number)prop.value()); - } else if (prop.value() instanceof List) { - Gson gson = new Gson(); - String list = gson.toJson(prop.value()); - - json.addProperty(prop.key(), list); - } else { - //throw exception? - return null; - } + @Override + public JsonObject createPropertiesObject(Vertex v) throws AAIFormatVertexException { + try { + final Introspector obj = loader.introspectorFromName( + v.property(AAIProperties.NODE_TYPE) + .orElse(null) + ); + + final List wrapper = new ArrayList<>(); + + wrapper.add(v); + + try { + serializer.dbToObject(wrapper, obj, this.depth, false, "false"); + } catch (AAIException | UnsupportedEncodingException e) { + throw new AAIFormatVertexException("Failed to format vertex - error while serializing: " + e.getMessage(), e); } + + final String json = obj.marshal(false); + return parser.parse(json).getAsJsonObject(); + } catch (AAIUnknownObjectException e) { + throw new AAIFormatVertexException("Failed to format vertex - unknown object", e); } - return json; - } - - private JsonArray createRelationshipObject(Vertex v) throws AAIFormatVertexException { - JsonArray jarray = new JsonArray(); - Iterator iter = v.vertices(Direction.BOTH); - - while (iter.hasNext()) { - Vertex related = iter.next(); - - JsonObject json = new JsonObject(); - json.addProperty("id", related.id().toString()); - json.addProperty("node-type", related.value(AAIProperties.NODE_TYPE)); - json.addProperty("url", this.urlBuilder.pathed(related)); - jarray.add(json); - } - - return jarray; + } } diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/exceptions/QueryParamInjectionException.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/exceptions/QueryParamInjectionException.java new file mode 100644 index 00000000..6f75e3ba --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/exceptions/QueryParamInjectionException.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.openecomp.aai.serialization.queryformats.exceptions; + +import org.openecomp.aai.exceptions.AAIException; + +public class QueryParamInjectionException extends AAIException { + + private static final long serialVersionUID = -5575661036426538012L; + + public QueryParamInjectionException(String message) { + super("AAI_4017", message); + } + + public QueryParamInjectionException(Throwable cause) { + super("AAI_4017",cause); + } + + public QueryParamInjectionException(String message, Throwable cause) { + super("AAI_4017", cause, message); + } +} diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Depth.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Depth.java new file mode 100644 index 00000000..d5ade869 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Depth.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.openecomp.aai.serialization.queryformats.params; + +@Inject(name = "depth") +public interface Depth { + + @Setter + public T depth(Integer depth); +} diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Inject.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Inject.java new file mode 100644 index 00000000..128b7394 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Inject.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.openecomp.aai.serialization.queryformats.params; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Inject { + + /** + * The way the query parameter appears in the URI + * @return + */ + String name(); +} diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/NodesOnly.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/NodesOnly.java new file mode 100644 index 00000000..e81b5447 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/NodesOnly.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.openecomp.aai.serialization.queryformats.params; + +@Inject(name = "nodesOnly") +public interface NodesOnly { + + @Setter + public T nodesOnly(Boolean nodesOnly); +} diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Setter.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Setter.java new file mode 100644 index 00000000..ad866c22 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/params/Setter.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.openecomp.aai.serialization.queryformats.params; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +/** + * Marks what method in the object should be used for setting the value + * of the query parameter + */ +public @interface Setter { + +} diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/utils/QueryParamInjector.java b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/utils/QueryParamInjector.java new file mode 100644 index 00000000..c67ed788 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/queryformats/utils/QueryParamInjector.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.openecomp.aai.serialization.queryformats.utils; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Set; + +import javax.ws.rs.core.MultivaluedMap; + +import org.openecomp.aai.serialization.queryformats.exceptions.QueryParamInjectionException; +import org.openecomp.aai.serialization.queryformats.params.Inject; +import org.openecomp.aai.serialization.queryformats.params.Setter; +import org.reflections.Reflections; + +public class QueryParamInjector { + + private final Set> results; + + + private QueryParamInjector () { + Reflections reflections = new Reflections("org.openecomp.aai.serialization.queryformats.params"); + results = reflections.getTypesAnnotatedWith(Inject.class); + } + + private static class Helper { + private static final QueryParamInjector INSTANCE = new QueryParamInjector(); + } + + public static QueryParamInjector getInstance() { + return Helper.INSTANCE; + } + + public T injectParams(T obj, MultivaluedMap params) throws QueryParamInjectionException{ + try { + for (Class item : results) { + if (item.isAssignableFrom(obj.getClass())) { + String name = item.getAnnotation(Inject.class).name(); + + if (params.containsKey(name)) { + String value = params.getFirst(name); + + for (Method method : item.getMethods()) { + if (method.isAnnotationPresent(Setter.class)) { + Class[] args = method.getParameterTypes(); + if (args.length == 1) { + Object o = args[0].getConstructor(String.class).newInstance(value); + method.invoke(obj, o); + } else { + method.invoke(obj); + } + } + } + } + } + } + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException + | SecurityException e) { + throw new QueryParamInjectionException("issue with query params", e); + } + + + return obj; + } +} diff --git a/aai-core/src/test/java/org/openecomp/aai/serialization/queryformats/SimpleFormatTest.java b/aai-core/src/test/java/org/openecomp/aai/serialization/queryformats/SimpleFormatTest.java new file mode 100644 index 00000000..51ccd363 --- /dev/null +++ b/aai-core/src/test/java/org/openecomp/aai/serialization/queryformats/SimpleFormatTest.java @@ -0,0 +1,177 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.openecomp.aai.serialization.queryformats; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import java.io.UnsupportedEncodingException; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.T; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.openecomp.aai.dbmap.DBConnectionType; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.introspection.LoaderFactory; +import org.openecomp.aai.introspection.ModelType; +import org.openecomp.aai.introspection.Version; +import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; +import org.openecomp.aai.serialization.db.DBSerializer; +import org.openecomp.aai.serialization.engines.QueryStyle; +import org.openecomp.aai.serialization.engines.TitanDBEngine; +import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; +import org.openecomp.aai.serialization.queryformats.exceptions.AAIFormatVertexException; +import org.openecomp.aai.serialization.queryformats.utils.UrlBuilder; +import org.openecomp.aai.util.AAIConstants; + +import com.google.gson.JsonObject; + +public class SimpleFormatTest { + + @Mock + private UrlBuilder urlBuilder; + + private Graph graph; + private TransactionalGraphEngine dbEngine; + private Loader loader; + private DBSerializer serializer; + private RawFormat simpleFormat; + private Vertex vfModule; + + + + private final ModelType factoryType = ModelType.MOXY; + + @Before + public void setUp() throws Exception { + + MockitoAnnotations.initMocks(this); + + System.setProperty("AJSC_HOME", "src/test/resources"); + System.setProperty("BUNDLECONFIG_DIR", "bundleconfig-local"); + QueryFormatTestHelper.setFinalStatic(AAIConstants.class.getField("AAI_HOME_ETC_OXM"), + "src/test/resources/org/openecomp/aai/introspection/"); + + graph = TinkerGraph.open(); + + vfModule = graph.addVertex( + T.label, "vf-module", + T.id, "5", + "aai-node-type", "vf-module", + "vf-module-id", "vf-module-id-val-68205", + "vf-module-name", "example-vf-module-name-val-68205", + "heat-stack-id", "example-heat-stack-id-val-68205", + "orchestration-status", "example-orchestration-status-val-68205", + "is-base-vf-module", "true", + "resource-version", "1498166571906", + "model-invariant-id", "fe8aac07-ce6c-4f9f-aa0d-b561c77da9e8", + "model-invariant-id-local", "fe8aac07-ce6c-4f9f-aa0d-b561c77da9e8", + "model-version-id", "0d23052d-8ffe-433e-a25d-da5da027bb7c", + "model-version-id-local", "0d23052d-8ffe-433e-a25d-da5da027bb7c", + "widget-model-id", "example-widget-model-id-val-68205", + "widget-model-version", "example-widget--model-version-val-68205", + "contrail-service-instance-fqdn", "example-contrail-service-instance-fqdn-val-68205" + ); + } + + @Test + public void testCreatePropertiesObjectReturnsProperProperties() throws AAIFormatVertexException, AAIException { + + createLoaderEngineSetup(); + serializer = new DBSerializer(Version.v10, dbEngine, factoryType, "Junit"); + simpleFormat = new RawFormat.Builder(loader, serializer, urlBuilder).nodesOnly(true).depth(0).modelDriven().build(); + + assertNotNull(dbEngine.tx()); + assertNotNull(dbEngine.asAdmin()); + + JsonObject json = simpleFormat.createPropertiesObject(vfModule); + + assertTrue(json.has("model-invariant-id")); + assertTrue(json.has("model-version-id")); + + assertFalse(json.has("model-invariant-id-local")); + assertFalse(json.has("model-version-id-local")); + + } + + @Ignore + @Test(expected = AAIFormatVertexException.class) + public void testCreatePropertiesObjectThrowsExceptionIfSerializationFails() throws AAIFormatVertexException, AAIException, UnsupportedEncodingException { + + serializer = mock(DBSerializer.class); + loader = mock(Loader.class); + + simpleFormat = new RawFormat.Builder(loader, serializer, urlBuilder).nodesOnly(true).depth(0).build(); + + when(serializer.dbToObject(anyObject(), anyObject(), anyInt(), anyBoolean(), anyString())) + .thenThrow(new AAIException("Test Exception")); + + simpleFormat.createPropertiesObject(vfModule); + } + + @Ignore + @Test(expected = AAIFormatVertexException.class) + public void testCreatePropertiesObjectThrowsExceptionIfUnknownObject() throws AAIFormatVertexException, AAIException, UnsupportedEncodingException { + + loader = mock(Loader.class); + serializer = mock(DBSerializer.class); + + simpleFormat = new RawFormat.Builder(loader, serializer, urlBuilder).nodesOnly(true).depth(0).build(); + + when(loader.introspectorFromName(anyString())) + .thenThrow(new AAIUnknownObjectException("Test Exception")); + + simpleFormat.createPropertiesObject(vfModule); + } + + public void createLoaderEngineSetup(){ + + if(loader == null){ + loader = LoaderFactory.createLoaderForVersion(factoryType, Version.v10); + dbEngine = spy(new TitanDBEngine(QueryStyle.TRAVERSAL, DBConnectionType.CACHED, loader)); + + TransactionalGraphEngine.Admin spyAdmin = spy(dbEngine.asAdmin()); + + when(dbEngine.tx()).thenReturn(graph); + when(dbEngine.asAdmin()).thenReturn(spyAdmin); + + when(spyAdmin.getReadOnlyTraversalSource()).thenReturn(graph.traversal(GraphTraversalSource.build().with(ReadOnlyStrategy.instance()))); + when(spyAdmin.getTraversalSource()).thenReturn(graph.traversal()); + } + } +} diff --git a/aai-core/src/test/java/org/openecomp/aai/serialization/queryformats/utils/QueryParamInjectorTest.java b/aai-core/src/test/java/org/openecomp/aai/serialization/queryformats/utils/QueryParamInjectorTest.java new file mode 100644 index 00000000..d5a09ece --- /dev/null +++ b/aai-core/src/test/java/org/openecomp/aai/serialization/queryformats/utils/QueryParamInjectorTest.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.openecomp.aai.serialization.queryformats.utils; + +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; + +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.serialization.db.DBSerializer; +import org.openecomp.aai.serialization.queryformats.Resource; +import org.openecomp.aai.serialization.queryformats.Resource.Builder; + +public class QueryParamInjectorTest { + + + @Mock private Loader loader; + @Mock private DBSerializer serializer; + @Mock private UrlBuilder urlBuilder; + + @Test + public void test() throws AAIException { + MockitoAnnotations.initMocks(this); + QueryParamInjector injector = QueryParamInjector.getInstance(); + + Builder b = new Resource.Builder(loader, serializer, urlBuilder); + MultivaluedMap params = new MultivaluedHashMap<>(); + params.putSingle("nodesOnly", "true"); + params.putSingle("depth", "10"); + params.putSingle("invalid", "1000"); + injector.injectParams(b, params); + + assertEquals("is nodes only", true, b.isNodesOnly()); + assertEquals("is depth 10", 10, b.getDepth()); + } +} -- 2.16.6