aboutsummaryrefslogtreecommitdiffstats
path: root/ms/neng/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'ms/neng/src/main')
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/exceptions/NengException.java32
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/NameGenerator.java499
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/SeqGenData.java88
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/SequenceFormatter.java44
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/persistence/NamePersister.java53
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/resource/model/AaiResponse.java40
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/rs/interceptors/AaiAuthorizationInterceptor.java53
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/seq/SequenceGenerator.java101
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/validator/AaiNameValidator.java53
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/validator/DbNameValidator.java43
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/extinf/props/AaiProps.java104
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/extinf/props/PolicyManagerProps.java92
-rw-r--r--ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/service/extinf/impl/AaiServiceImpl.java131
13 files changed, 1333 insertions, 0 deletions
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/exceptions/NengException.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/exceptions/NengException.java
new file mode 100644
index 00000000..cad15759
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/exceptions/NengException.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.exceptions;
+
+/**
+ * Represents application exceptions generated by this micro-service.
+ */
+public class NengException extends Exception {
+ static final long serialVersionUID = -3387516993124229948L;
+
+ public NengException(String message) {
+ super(message);
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/NameGenerator.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/NameGenerator.java
new file mode 100644
index 00000000..8cfe7c88
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/NameGenerator.java
@@ -0,0 +1,499 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.gen;
+
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.namingModel;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.namingModelRelaxed;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.namingModels;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.namingOperation;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.namingProperty;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.namingRecipe;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.namingType;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.propertyValue;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.relaxedNamingType;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.seq;
+import static org.onap.ccsdk.apps.ms.neng.core.policy.PolicyReader.value;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.onap.ccsdk.apps.ms.neng.core.exceptions.NengException;
+import org.onap.ccsdk.apps.ms.neng.core.persistence.NamePersister;
+import org.onap.ccsdk.apps.ms.neng.core.policy.PolicyFinder;
+import org.onap.ccsdk.apps.ms.neng.core.policy.PolicyParameters;
+import org.onap.ccsdk.apps.ms.neng.core.policy.PolicySequence;
+import org.onap.ccsdk.apps.ms.neng.core.policy.PropertyOperator;
+import org.onap.ccsdk.apps.ms.neng.core.policy.RecipeParser;
+import org.onap.ccsdk.apps.ms.neng.core.seq.SequenceGenerator;
+import org.onap.ccsdk.apps.ms.neng.core.validator.AaiNameValidator;
+import org.onap.ccsdk.apps.ms.neng.core.validator.DbNameValidator;
+import org.onap.ccsdk.apps.ms.neng.persistence.entity.GeneratedName;
+
+/**
+ * Generates names of network elements based on policy data.
+ */
+public class NameGenerator {
+ private static final String RESOURCE_NAME_ELEMENT_ITEM = "resource-name";
+ private static final String RESOURCE_VALUE_ELEMENT_ITEM = "resource-value";
+ private static final String EXTERNAL_KEY_ELEMENT_ITEM = "external-key";
+ private static final String NAMING_TYPE_ELEMENT_ITEM = "naming-type";
+
+ private final PolicyFinder policyFinder;
+ private final PolicyParameters policyParams;
+ private final SequenceGenerator seqGenerator;
+ private final DbNameValidator dbValidator;
+ private final AaiNameValidator aaiValidator;
+ private final NamePersister namePersister;
+ private final Map<String, String> requestElement;
+ private final List<Map<String, String>> allElements;
+ private final Map<String, Map<String, String>> earlierNames;
+ private final Map<String, Map<String, ?>> policyCache;
+
+ /**
+ * Constructor.
+ *
+ * @param policyFinder a way to find policies
+ * @param policyParams parameters related to policy
+ * @param seqGenerator a way to generate sequences
+ * @param dbValidator a way to validate generated names against DB
+ * @param aaiValidator a way to validate generated names against A&AI
+ * @param namePersister a way to persist names
+ * @param requestElement the request element for which the name is generated, containing data such
+ * as policy name, naming-type, external-key and resource-name
+ * @param allElements all the elements in the request (including the current request element for
+ * which name is generated), as this is needed to re-use names generated from other request elements
+ * within the same transaction
+ * @param earlierNames names generated earlier in the same transaction, as a map from naming-type
+ * to names (which is a map with keys "resource-name", "resource-value" and "external-key")
+ * @param policyCache cache containing policies retrieved in this transaction, to avoid repeated
+ * calls to policy manager within the same transaction
+ */
+ public NameGenerator(PolicyFinder policyFinder, PolicyParameters policyParams, SequenceGenerator seqGenerator,
+ DbNameValidator dbValidator, AaiNameValidator aaiValidator, NamePersister namePersister,
+ Map<String, String> requestElement, List<Map<String, String>> allElements,
+ Map<String, Map<String, String>> earlierNames, Map<String, Map<String, ?>> policyCache) {
+ this.policyFinder = policyFinder;
+ this.policyParams = policyParams;
+ this.seqGenerator = seqGenerator;
+ this.dbValidator = dbValidator;
+ this.aaiValidator = aaiValidator;
+ this.namePersister = namePersister;
+ this.requestElement = requestElement;
+ this.allElements = allElements;
+ this.earlierNames = earlierNames;
+ this.policyCache = policyCache;
+ }
+
+ /**
+ * Generates the name.
+ *
+ * @return the map (with keys "resource-name", "resource-value" and "external-key") containing the name.
+ */
+ public Map<String, String> generate() throws Exception {
+ String policyName = findElementPolicyName();
+ if (policyName == null) {
+ throw new NengException("Could not find policy name in the request");
+ }
+ String namingType = findElementNamingType();
+ if (namingType != null) {
+ Map<String, String> generated = this.earlierNames.get(namingType);
+ if (generated != null) {
+ return generated;
+ }
+ return generateNew(policyName, namingType);
+ } else {
+ throw new NengException("Could not find naming type in the request for policy " + policyName);
+ }
+ }
+
+ String applyNameOperation(Map<String, ?> namingModel, String name) throws Exception {
+ String nameOperation = namingOperation(namingModel);
+ if (nameOperation != null && !"".equals(nameOperation)) {
+ name = new PropertyOperator().apply(name, nameOperation, this.policyParams);
+ }
+ return name;
+ }
+
+ String applyPropertyOperation(String value, Map<String, ?> propertyMap) throws Exception {
+ return new PropertyOperator().apply(value, propertyMap, this.policyParams);
+ }
+
+ static Map<String, String> buildResponse(String key, String name, String value) {
+ Map<String, String> response = new HashMap<String, String>();
+ response.put(EXTERNAL_KEY_ELEMENT_ITEM, key);
+ response.put(RESOURCE_NAME_ELEMENT_ITEM, name);
+ response.put(RESOURCE_VALUE_ELEMENT_ITEM, value);
+ return response;
+ }
+
+ String buildSequenceSuffix(Map<String, Object> recipeValues, String recipeName, List<String> recipe)
+ throws Exception {
+ StringBuffer buf = new StringBuffer();
+ boolean postItem = false;
+ for (String key : recipe) {
+ if (postItem) {
+ buf.append(recipeValues.get(key).toString());
+ } else if (key.equals(recipeName)) {
+ postItem = true;
+ }
+ }
+ String value = buf.toString();
+ if (value.length() == 0) {
+ value = null;
+ }
+ return value;
+ }
+
+ String buildSequencePrefix(Map<String, Object> recipeValues, String recipeName, List<String> recipe)
+ throws Exception {
+ StringBuffer buf = new StringBuffer();
+ for (String key : recipe) {
+ if (key.equals(recipeName)) {
+ break;
+ }
+ buf.append(recipeValues.get(key).toString());
+ }
+ return buf.toString();
+ }
+
+ Map<String, String> generateNew(String policyName, String namingType) throws Exception {
+ Map<String, ?> policy = findPolicy(policyName);
+ if (policy != null) {
+ List<Map<String, ?>> namingModels = namingModels(policy);
+ Map<String, ?> namingModel = namingModel(namingModels, namingType);
+ if (namingModel == null) {
+ throw new NengException(
+ "Could not find the policy data for " + policyName + " and naming-type " + namingType);
+ }
+ return generateNew(policyName, namingType, namingModels, namingModel);
+ } else {
+ throw new NengException("Could not find the policy data for " + policyName);
+ }
+ }
+
+ Map<String, String> generateNew(String policyName, String namingType,
+ List<Map<String, ?>> namingModels, Map<String, ?> namingModel) throws Exception {
+ String recipe = namingRecipe(namingModel);
+ if (recipe == null) {
+ throw new NengException("Could not find the recipe for "
+ + policyName + " and naming-type " + namingType);
+ }
+ List<String> recipeItems = RecipeParser.parseRecipe(this.policyParams, recipe);
+ return generateNew(namingModels, policyName, namingType, namingModel, recipeItems);
+ }
+
+ Map<String, String> generateNew(List<Map<String, ?>> namingModels, String policyName,
+ String namingType, Map<String, ?> namingModel, List<String> recipe) throws Exception {
+ Map<String, Object> recipeValues = new LinkedHashMap<>();
+ for (String recipeItem : recipe) {
+ Map<String, ?> propMap = namingProperty(namingModel, recipeItem);
+ if ("SEQUENCE".equals(recipeItem)) {
+ PolicySequence seq = seq(propMap);
+ recipeValues.put(recipeItem, seq);
+ } else {
+ String val = generateNonSequenceValue(namingModels, policyName, namingType, namingModel, propMap,
+ recipeItem);
+ if (val != null) {
+ recipeValues.put(recipeItem, val);
+ }
+ }
+ }
+ validateAllItemsPresent(policyName, namingType, recipe, recipeValues);
+ SeqGenData seqData = generateNameWithSequences(policyName, namingType, recipe, recipeValues, namingModel);
+ String name = seqData.getName();
+ storeGeneratedName(findElementExternalKey(), name, namingType, seqData);
+ Map<String, String> response = buildResponse(findElementExternalKey(), findElementResourceName(), name);
+ String relaxedNamingType = relaxedNamingType(namingType);
+ this.earlierNames.put(relaxedNamingType, response);
+ return response;
+ }
+
+ SeqGenData generateNameWithSequences(String policyName, String namingType, List<String> recipe,
+ Map<String, Object> recipeValues, Map<String, ?> namingModel) throws Exception {
+ int attemptCount = 0;
+ int maxGenAttempt = this.policyParams.getMaxGenAttempt();
+ if (maxGenAttempt <= 0) {
+ maxGenAttempt = 1;
+ }
+ String name = null;
+ SeqGenData lastSeq = null;
+ boolean valid = false;
+ String additionalErrorMsg = "";
+ while (attemptCount <= maxGenAttempt && !valid) {
+ ++attemptCount;
+ lastSeq = generateSequenceValues(policyName, namingType, recipe, recipeValues, lastSeq, attemptCount);
+ name = generateNameFromSegments(recipeValues, recipe);
+ boolean sequenceLess = false;
+ if (lastSeq == null) {
+ lastSeq = new SeqGenData();
+ sequenceLess = true;
+ }
+ name = applyNameOperation(namingModel, name);
+ lastSeq.setName(name);
+ valid = this.dbValidator.validate(namingType, name);
+ if (valid) {
+ valid = this.aaiValidator.validate(namingType, name);
+ if (!valid) {
+ storeGeneratedName("AAI-BACKPOPULATE", name, namingType, lastSeq);
+ additionalErrorMsg = "AAI Name validation failed";
+ }
+ } else {
+ additionalErrorMsg = "DB Name validation failed";
+ }
+ if (sequenceLess) {
+ break; // handle names with no sequence in them
+ }
+ }
+ if (attemptCount > maxGenAttempt) {
+ throw new NengException("Could not generate a name successfully for policy " + policyName
+ + " and naming-type " + namingType + " even after " + maxGenAttempt + " attempts.");
+ }
+ if (!valid) {
+ throw new NengException("Could not generate a valid name successfully for policy " + policyName
+ + " and naming-type " + namingType + ". " + additionalErrorMsg);
+ }
+ return lastSeq;
+ }
+
+ String generateNameFromSegments(Map<String, Object> recipeValues, List<String> recipe) throws Exception {
+ StringBuffer buf = new StringBuffer();
+ for (String recName : recipe) {
+ Object val = recipeValues.get(recName);
+ if (val instanceof PolicySequence) {
+ PolicySequence poly = (PolicySequence) val;
+ buf.append(poly.getValue());
+ } else {
+ buf.append(val.toString());
+ }
+ }
+ String value = buf.toString();
+ return value;
+ }
+
+ SeqGenData generateSequenceValues(String policyName, String namingType, List<String> recipe,
+ Map<String, Object> recipeValues, SeqGenData lastSeq, int attemptCount) throws Exception {
+ SeqGenData precedSeq = generateSequenceValuesOfScope(
+ policyName, namingType, recipe, recipeValues, "PRECEEDING", lastSeq, attemptCount);
+ SeqGenData entireSeq = generateSequenceValuesOfScope(
+ policyName, namingType, recipe, recipeValues, "ENTIRETY", lastSeq, attemptCount);
+ if (entireSeq != null) {
+ return entireSeq;
+ }
+ return precedSeq;
+ }
+
+ SeqGenData generateSequenceValuesOfScope(String policyName, String namingType, List<String> recipe,
+ Map<String, Object> recipeValues, String scope, SeqGenData lastSeq, int attemptCount)
+ throws Exception {
+ for (String item : recipe) {
+ Object val = recipeValues.get(item);
+ if (val instanceof PolicySequence) {
+ PolicySequence seq = (PolicySequence) val;
+ if (scope.equals(seq.getScope())) {
+ SeqGenData seqVal = generateSequenceValue(
+ seq, policyName, namingType, recipeValues, item, lastSeq, attemptCount, recipe);
+ String seqStr = SequenceFormatter.formatSequence(seqVal.getSeq(), seq);
+ seqVal.setSeqEncoded(seqStr);
+ seq.setKey(item);
+ seq.setValue(seqStr);
+ return seqVal;
+ }
+ }
+ }
+ return null;
+ }
+
+ SeqGenData generateSequenceValue(PolicySequence seq, String policyName, String namingType,
+ Map<String, Object> recipeValues, String recipeName, SeqGenData lastSeq, int attemptCount,
+ List<String> recipe) throws Exception {
+ String prefix = buildSequencePrefix(recipeValues, recipeName, recipe);
+ String suffix = buildSequenceSuffix(recipeValues, recipeName, recipe);
+ SeqGenData seqData = new SeqGenData();
+ Long lastSeqValue = null;
+ if (lastSeq != null) {
+ lastSeqValue = lastSeq.getSeq();
+ }
+ long seqValue = this.seqGenerator.generate(prefix, suffix, seq, lastSeqValue, attemptCount);
+ seqData.setSeq(seqValue);
+ seqData.setPrefix(prefix);
+ seqData.setSuffix(suffix);
+ return seqData;
+ }
+
+ String generateNonSequenceValue(List<Map<String, ?>> namingModels, String policyName, String namingType,
+ Map<String, ?> namingModel, Map<String, ?> propMap, String recipeItem) throws Exception {
+ String val = propertyValue(propMap);
+ if (val == null) {
+ val = value(this.requestElement, recipeItem);
+ }
+ if (val == null) {
+ val = value(this.requestElement, recipeItem, true);
+ }
+ if (val == null) {
+ val = generateValueRecursively(namingModels, policyName, recipeItem);
+ }
+ if (val != null) {
+ val = applyPropertyOperation(val, propMap);
+ }
+ return val;
+ }
+
+ String generateValueRecursively(List<Map<String, ?>> namingModels, String policyName, String recipeItem)
+ throws Exception {
+ String val = null;
+ String relaxedVal = relaxedNamingType(recipeItem);
+ Map<String, String> generated = this.earlierNames.get(relaxedVal);
+ if (generated != null) {
+ return generated.get("resource-value");
+ }
+ Map<String, ?> relaxedModel = namingModelRelaxed(namingModels, recipeItem);
+ if (relaxedModel != null) {
+ String relaxedNamingType = namingType(relaxedModel);
+ Map<String, String> relaxedElement = findElement(relaxedNamingType);
+ if (relaxedElement != null) {
+ relaxedElement = new HashMap<>(relaxedElement);
+ relaxedElement.put(NAMING_TYPE_ELEMENT_ITEM, relaxedNamingType);
+ } else {
+ relaxedElement = new HashMap<>(this.requestElement);
+ relaxedElement.put(NAMING_TYPE_ELEMENT_ITEM, relaxedNamingType);
+ relaxedElement.remove(EXTERNAL_KEY_ELEMENT_ITEM);
+ relaxedElement.remove(RESOURCE_NAME_ELEMENT_ITEM);
+ }
+ if (relaxedElement != null) {
+ NameGenerator recursive = new NameGenerator(policyFinder, policyParams, seqGenerator, dbValidator,
+ aaiValidator, namePersister, relaxedElement, allElements, earlierNames, policyCache);
+ Map<String, String> gen =
+ recursive.generateNew(policyName, relaxedNamingType, namingModels, relaxedModel);
+ if (gen != null) {
+ val = value(gen, RESOURCE_VALUE_ELEMENT_ITEM);
+ }
+ }
+ }
+ return val;
+ }
+
+ Map<String, String> findElement(String namingType) throws Exception {
+ Map<String, String> theElement = null;
+ for (Map<String, String> anElement : this.allElements) {
+ String oneNamingType = namingType(anElement);
+ if (namingType.equals(oneNamingType)) {
+ theElement = anElement;
+ break;
+ }
+ }
+ return theElement;
+ }
+
+ String findElementPolicyName() throws Exception {
+ return value(this.requestElement, "policy-instance-name");
+ }
+
+ String findElementNamingType() throws Exception {
+ return value(this.requestElement, NAMING_TYPE_ELEMENT_ITEM);
+ }
+
+ String findElementResourceName() throws Exception {
+ return value(this.requestElement, RESOURCE_NAME_ELEMENT_ITEM);
+ }
+
+ String findElementExternalKey() throws Exception {
+ return value(this.requestElement, EXTERNAL_KEY_ELEMENT_ITEM);
+ }
+
+ Map<String, ?> findPolicy(String name) throws Exception {
+ Map<String, ?> policy = null;
+ if (name != null) {
+ policy = this.policyCache.get(name);
+ if (policy == null) {
+ policy = this.policyFinder.findPolicy(name);
+ if (policy != null) {
+ this.policyCache.put(name, policy);
+ }
+ }
+ }
+ return policy;
+ }
+
+ void storeGeneratedName(String key, String name, String namingType,
+ SeqGenData seqData) throws Exception {
+ String prefix = null;
+ String suffix = null;
+ Long seqNum = null;
+ String seqEncoded = null;
+ if (seqData != null) {
+ prefix = seqData.getPrefix();
+ suffix = seqData.getSuffix();
+ seqNum = seqData.getSeq();
+ seqEncoded = seqData.getSeqEncoded();
+ }
+ GeneratedName record = new GeneratedName();
+ GeneratedName releasedName = namePersister.findBy(namingType, name, "Y");
+ if (releasedName != null) {
+ record = releasedName;
+ record.setLastUpdatedTime(new Timestamp(System.currentTimeMillis()));
+ record.setIsReleased(null);
+ }
+ record.setName(name);
+ record.setExternalId(key);
+ record.setElementType(namingType);
+ record.setPrefix(prefix);
+ record.setSuffix(suffix);
+ if (seqNum != null) {
+ record.setSequenceNumber(seqNum);
+ }
+ record.setSequenceNumberEnc(seqEncoded);
+ this.namePersister.persist(record);
+ }
+
+ void validateAllItemsPresent(String policyName, String namingType, List<String> recipe,
+ Map<String, Object> recipeValues) throws Exception {
+ List<String> missing = new ArrayList<>();
+ for (String item : recipe) {
+ Object val = recipeValues.get(item);
+ if (val == null) {
+ missing.add(item);
+ }
+ }
+ if (missing.size() > 0) {
+ StringBuffer msg = new StringBuffer();
+ for (int i = 0; i < missing.size(); ++i) {
+ String item = missing.get(i);
+ if (i > 0) {
+ String separator = ", ";
+ if (i == missing.size() - 1) {
+ separator = " and ";
+ }
+ msg.append(separator);
+ }
+ msg.append(item);
+ }
+ String itemString = "items";
+ if (missing.size() == 1) {
+ itemString = "item";
+ }
+ throw new NengException("Could not find data for recipe " + itemString + " " + msg.toString()
+ + " in policy " + policyName + " and naming-type " + namingType);
+ }
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/SeqGenData.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/SeqGenData.java
new file mode 100644
index 00000000..1fe4dd1f
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/SeqGenData.java
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.gen;
+
+/**
+ * POJO representing a 'sequence' object defined in the policy, that controls the behavior
+ * of sequences used as part of a generated name.
+ */
+public class SeqGenData {
+ private String prefix;
+ private String suffix;
+ private long seq;
+ private String seqEncoded;
+ private String name;
+
+ /**
+ * Prefix for the sequence.
+ */
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ /**
+ * Suffix for the sequence.
+ */
+ public String getSuffix() {
+ return suffix;
+ }
+
+ public void setSuffix(String suffix) {
+ this.suffix = suffix;
+ }
+
+ /**
+ * The sequence item as an integer.
+ */
+ public long getSeq() {
+ return seq;
+ }
+
+ public void setSeq(long seq) {
+ this.seq = seq;
+ }
+
+ /**
+ * The name generated from the sequence.
+ */
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * The sequence item encoded into the appropriate form.
+ */
+ public String getSeqEncoded() {
+ return seqEncoded;
+ }
+
+ public void setSeqEncoded(String seqEncoded) {
+ this.seqEncoded = seqEncoded;
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/SequenceFormatter.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/SequenceFormatter.java
new file mode 100644
index 00000000..c25f101a
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/gen/SequenceFormatter.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.gen;
+
+import org.apache.commons.lang.StringUtils;
+import org.onap.ccsdk.apps.ms.neng.core.policy.PolicySequence;
+
+/**
+ * Utility for formatting a sequence.
+ */
+public class SequenceFormatter {
+ /**
+ * Format the given sequence item/value per the given sequence policy, and return the result
+ * as a string.
+ */
+ public static String formatSequence(long seqVal, PolicySequence seqPoly) throws Exception {
+ if (seqPoly.getType() == PolicySequence.Type.ALPHA) {
+ String val = Long.toString(seqVal, 36);
+ return StringUtils.leftPad(val, (int) seqPoly.getLength(), '0');
+ } else {
+ String format = "%0" + seqPoly.getLength() + "d";
+ String strVal = String.format(format, seqVal);
+ return strVal;
+ }
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/persistence/NamePersister.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/persistence/NamePersister.java
new file mode 100644
index 00000000..4875052b
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/persistence/NamePersister.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.persistence;
+
+import org.onap.ccsdk.apps.ms.neng.persistence.entity.GeneratedName;
+import org.onap.ccsdk.apps.ms.neng.persistence.repository.GeneratedNameRespository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Manages the persistence of generated names using a DB.
+ */
+@Component
+public class NamePersister {
+ @Autowired
+ GeneratedNameRespository repository;
+
+ /**
+ * Persist the given name.
+ */
+ public void persist(GeneratedName name) throws Exception {
+ repository.save(name);
+ }
+
+ /**
+ * Finds a name stored in the DB of the given type, name, and the 'isReleased' flag.
+ *
+ * @param elementType The type of the name
+ * @param name A name
+ * @param isReleased An Y/N flag indicating if the name is released or not
+ */
+ public GeneratedName findBy(String elementType, String name, String isReleased) {
+ return repository.findByElementTypeAndNameAndIsReleased(elementType, name, isReleased);
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/resource/model/AaiResponse.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/resource/model/AaiResponse.java
new file mode 100644
index 00000000..431f57b8
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/resource/model/AaiResponse.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.resource.model;
+
+/**
+ * POJO encapsulating response from A&AI query.
+ */
+public class AaiResponse {
+
+ private boolean recFound = false;
+
+ /**
+ * Indicates if an entry is found in A&AI for a name.
+ */
+ public boolean isRecFound() {
+ return recFound;
+ }
+
+ public void setRecFound(boolean recFound) {
+ this.recFound = recFound;
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/rs/interceptors/AaiAuthorizationInterceptor.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/rs/interceptors/AaiAuthorizationInterceptor.java
new file mode 100644
index 00000000..e91ee331
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/rs/interceptors/AaiAuthorizationInterceptor.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.rs.interceptors;
+
+import java.io.IOException;
+import org.onap.ccsdk.apps.ms.neng.extinf.props.AaiProps;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.stereotype.Component;
+
+/**
+ * Interceptor for adding authorization headers in the request to A&AI.
+ */
+@Component
+public class AaiAuthorizationInterceptor implements ClientHttpRequestInterceptor {
+ @Autowired
+ AaiProps aaiProps;
+
+ /**
+ * Intercepts the given request and adds additional headers, mainly for authorization.
+ */
+ @Override
+ public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body, ClientHttpRequestExecution executionChain)
+ throws IOException {
+ httpRequest.getHeaders().clear();
+ httpRequest.getHeaders().add("x-FromAppId", aaiProps.getFromAppId());
+ httpRequest.getHeaders().add("x-TransactionId", aaiProps.getTransactionId());
+ httpRequest.getHeaders().add("Accept", "application/json");
+ httpRequest.getHeaders().add("Content-Type", "application/json");
+ return executionChain.execute(httpRequest, body);
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/seq/SequenceGenerator.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/seq/SequenceGenerator.java
new file mode 100644
index 00000000..d69345f9
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/seq/SequenceGenerator.java
@@ -0,0 +1,101 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.seq;
+
+import java.util.regex.Pattern;
+import org.onap.ccsdk.apps.ms.neng.core.exceptions.NengException;
+import org.onap.ccsdk.apps.ms.neng.core.policy.PolicySequence;
+import org.onap.ccsdk.apps.ms.neng.persistence.entity.ServiceParameter;
+import org.onap.ccsdk.apps.ms.neng.persistence.repository.GeneratedNameRespository;
+import org.onap.ccsdk.apps.ms.neng.persistence.repository.ServiceParameterRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Generates the sequence number part of the name.
+ */
+@Component
+public class SequenceGenerator {
+ @Autowired
+ GeneratedNameRespository genNameRepo;
+
+ @Autowired
+ ServiceParameterRepository servParamRepo;
+
+ /**
+ * Returns the next free item in the sequence that can be used for a generated name.
+ *
+ * @param prefix the prefix for the generated name
+ * @param suffix the suffix for the generated name
+ * @param seqParams the sequence parameters as defined in the policy
+ * @param lastSequenceNumber the last sequence number used for name generation
+ * @param attemptCount the number of times a free sequence item was requested in this transaction
+ */
+ public long generate(String prefix, String suffix, PolicySequence seqParams,
+ Long lastSequenceNumber, int attemptCount) throws Exception {
+ Long newSeqNum = null;
+ long nextIncrement = 1;
+ if (seqParams.getLastReleaseSeqNumTried() != null) {
+ newSeqNum = genNameRepo.findNextReleasedSeq(seqParams.getLastReleaseSeqNumTried(), prefix, suffix);
+ if (newSeqNum == null) {
+ throw new Exception("Name generation failed since all available sequence numbers are already used.");
+ }
+ return newSeqNum;
+ }
+ String dbMaxSeqNum = genNameRepo.findMaxByPrefixAndSuffix(prefix, suffix);
+ if (attemptCount == 1) {
+ if (dbMaxSeqNum != null) {
+ newSeqNum = Long.parseLong(dbMaxSeqNum) + seqParams.getIncrement();
+ } else {
+ newSeqNum = seqParams.getStartValue();
+ }
+ } else {
+ if (dbMaxSeqNum == null) {
+ ServiceParameter incrementParam = servParamRepo.findByName("initial_increment");
+ if (incrementParam != null) {
+ String[] increments = Pattern.compile(",").split(incrementParam.getValue());
+ if (attemptCount <= increments.length) {
+ nextIncrement = Long.parseLong(increments[attemptCount - 2]);
+ } else {
+ nextIncrement = Long.parseLong(increments[increments.length - 1]);
+ }
+ newSeqNum = lastSequenceNumber + nextIncrement;
+ } else {
+ throw new NengException(
+ "Name generation failed since initial_increment parameter was not found.");
+ }
+ } else {
+ newSeqNum = lastSequenceNumber + seqParams.getIncrement();
+ }
+ }
+ if (newSeqNum > seqParams.getMaxValue()) {
+ newSeqNum = genNameRepo.findNextReleasedSeq(seqParams.getStartValue(), prefix, suffix);
+ if (newSeqNum != null) {
+ seqParams.setLastReleaseSeqNumTried(newSeqNum);
+ return newSeqNum;
+ } else {
+ throw new NengException(
+ "Name generation failed since all available sequence numbers are already used.");
+ }
+ }
+ return newSeqNum;
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/validator/AaiNameValidator.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/validator/AaiNameValidator.java
new file mode 100644
index 00000000..32f3df6a
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/validator/AaiNameValidator.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.validator;
+
+import java.util.logging.Logger;
+import org.onap.ccsdk.apps.ms.neng.persistence.repository.ExternalInterfaceRespository;
+import org.onap.ccsdk.apps.ms.neng.service.extinf.impl.AaiServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Validates that a generated name is valid, by comparing against A&AI.
+ */
+@Component
+public class AaiNameValidator {
+ @Autowired
+ AaiServiceImpl aaiImpl;
+ @Autowired
+ ExternalInterfaceRespository dbStuff;
+
+ private static Logger log = Logger.getLogger(AaiNameValidator.class.getName());
+
+ /**
+ * Returns true if the given name, of the given type, is valid.
+ */
+ public boolean validate(String namingType, String name) throws Exception {
+ log.info("AAI Validation called for " + namingType + " - " + name);
+ String url = dbStuff.getUriByNameType(namingType);
+ if (url == null) {
+ return true;
+ }
+ log.info("AAI URL " + url);
+ return aaiImpl.validate(url, name);
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/validator/DbNameValidator.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/validator/DbNameValidator.java
new file mode 100644
index 00000000..131144b9
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/core/validator/DbNameValidator.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.core.validator;
+
+import org.onap.ccsdk.apps.ms.neng.persistence.entity.GeneratedName;
+import org.onap.ccsdk.apps.ms.neng.persistence.repository.GeneratedNameRespository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Validates that a generated name is valid, by comparing against the internal DB of this micro-service.
+ */
+@Component
+public class DbNameValidator {
+ @Autowired
+ GeneratedNameRespository genNameRepo;
+
+ /**
+ * Returns true if the given name, of the given type, is valid.
+ */
+ public boolean validate(String namingType, String name) throws Exception {
+ GeneratedName genName = genNameRepo.findUnReleased(namingType, name);
+ return (genName == null) ? true : false;
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/extinf/props/AaiProps.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/extinf/props/AaiProps.java
new file mode 100644
index 00000000..dd831e87
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/extinf/props/AaiProps.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.extinf.props;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * POJO representing properties of the interface with A&AI.
+ */
+@Configuration
+@ConfigurationProperties(prefix = "aai")
+public class AaiProps {
+ String certPassword;
+ String cert;
+ String uriBase;
+ String fromAppId;
+ String transactionId;
+ String accept;
+
+ /**
+ * The certificate password.
+ */
+ public String getCertPassword() {
+ return certPassword;
+ }
+
+ public void setCertPassword(String certPassword) {
+ this.certPassword = certPassword;
+ }
+
+ /**
+ * The certificate.
+ */
+ public String getCert() {
+ return cert;
+ }
+
+ public void setCert(String cert) {
+ this.cert = cert;
+ }
+
+ /**
+ * Base/initial part of the A&AI URL.
+ */
+ public String getUriBase() {
+ return uriBase;
+ }
+
+ public void setUriBase(String auriBase) {
+ this.uriBase = auriBase;
+ }
+
+ /**
+ * The value to be used in the X-FromAppId header in the request to A&AI.
+ */
+ public String getFromAppId() {
+ return fromAppId;
+ }
+
+ public void setFromAppId(String fromAppId) {
+ this.fromAppId = fromAppId;
+ }
+
+ /**
+ * The value to be used in the X-TransactionId header in the request to A&AI.
+ */
+ public String getTransactionId() {
+ return transactionId;
+ }
+
+ public void setTransactionId(String transactionId) {
+ this.transactionId = transactionId;
+ }
+
+ /**
+ * The value to be used in the Accept header in the request to A&AI.
+ */
+ public String getAccept() {
+ return accept;
+ }
+
+ public void setAccept(String accept) {
+ this.accept = accept;
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/extinf/props/PolicyManagerProps.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/extinf/props/PolicyManagerProps.java
new file mode 100644
index 00000000..bd06f76c
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/extinf/props/PolicyManagerProps.java
@@ -0,0 +1,92 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.extinf.props;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * POJO for representing properties related to policy manager.
+ */
+@Configuration
+@ConfigurationProperties(prefix = "policymgr")
+public class PolicyManagerProps {
+ String clientAuth;
+ String basicAuth;
+ String url;
+ String environment;
+ String ecompRequestId;
+
+ /**
+ * Property passed to policy manager in the ClientAuth header.
+ */
+ public String getClientAuth() {
+ return clientAuth;
+ }
+
+ public void setClientAuth(String clientAuth) {
+ this.clientAuth = clientAuth;
+ }
+
+ /**
+ * Property passed to policy manager in the BasicAuth header.
+ */
+ public String getBasicAuth() {
+ return basicAuth;
+ }
+
+ public void setBasicAuth(String basicAuth) {
+ this.basicAuth = basicAuth;
+ }
+
+ /**
+ * URL of the policy manager.
+ */
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ /**
+ * Property passed to policy manager in the Environment header.
+ */
+ public String getEnvironment() {
+ return environment;
+ }
+
+ public void setEnvironment(String environment) {
+ this.environment = environment;
+ }
+
+ /**
+ * Property passed to policy manager in the X-ECOMP-RequestID header.
+ */
+ public String getEcompRequestId() {
+ return ecompRequestId;
+ }
+
+ public void setEcompRequestId(String ecompRequestId) {
+ this.ecompRequestId = ecompRequestId;
+ }
+}
diff --git a/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/service/extinf/impl/AaiServiceImpl.java b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/service/extinf/impl/AaiServiceImpl.java
new file mode 100644
index 00000000..a401d214
--- /dev/null
+++ b/ms/neng/src/main/java/org/onap/ccsdk/apps/ms/neng/service/extinf/impl/AaiServiceImpl.java
@@ -0,0 +1,131 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.apps
+ * ================================================================================
+ * Copyright (C) 2018 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.onap.ccsdk.apps.ms.neng.service.extinf.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.KeyStore;
+import java.util.logging.Logger;
+import javax.net.ssl.SSLContext;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.onap.ccsdk.apps.ms.neng.core.exceptions.NengException;
+import org.onap.ccsdk.apps.ms.neng.core.resource.model.AaiResponse;
+import org.onap.ccsdk.apps.ms.neng.core.rs.interceptors.AaiAuthorizationInterceptor;
+import org.onap.ccsdk.apps.ms.neng.extinf.props.AaiProps;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Implements interface with A&AI.
+ */
+@Service
+public class AaiServiceImpl {
+ private static final Logger log = Logger.getLogger(AaiServiceImpl.class.getName());
+
+ @Autowired AaiProps aaiProps;
+ RestTemplate restTemplate;
+ @Autowired AaiAuthorizationInterceptor authInt;
+
+ @Autowired
+ @Qualifier("aaiRestTempBuilder")
+ RestTemplateBuilder aaiRestTempBuilder;
+
+ /**
+ * Validates the given network element name against A&AI, using the given URL.
+ * @param url the URL for A&AI
+ * @param name a generated network element name
+ * @return true if the element name is valid
+ */
+ public boolean validate(String url, String name) throws Exception {
+ AaiResponse resp = makeOutboundCall(url, name);
+ return !resp.isRecFound();
+ }
+
+ AaiResponse makeOutboundCall(String url, String name) throws Exception {
+ String uri = aaiProps.getUriBase() + url + name;
+ log.info("AAI URI - " + uri);
+ ResponseEntity<Object> resp = null;
+ try {
+ RequestEntity<Void> re = RequestEntity.get(new URI(uri)).build();
+ resp = getRestTemplate().exchange(re, Object.class);
+ if (HttpStatus.OK.equals(resp.getStatusCode())) {
+ ObjectMapper objectmapper = new ObjectMapper();
+ log.info(objectmapper.writeValueAsString(resp.getBody()));
+ return buildResponse(true);
+ } else if (HttpStatus.NOT_FOUND.equals(resp.getStatusCode())) {
+ log.warning(resp.toString());
+ return buildResponse(false);
+ } else {
+ log.warning(resp.toString());
+ throw new NengException("Error while validating name with A&AI");
+ }
+ } catch (HttpClientErrorException e) {
+ log.warning(e.getStatusCode().name() + " -- " + e.getResponseBodyAsString());
+ if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
+ return buildResponse(false);
+ }
+ throw new NengException("Error while validating name with AAI");
+ }
+ }
+
+ AaiResponse buildResponse(boolean found) {
+ AaiResponse aaiResp = new AaiResponse();
+ aaiResp.setRecFound(found);
+ return aaiResp;
+ }
+
+ RestTemplate getRestTemplate() throws Exception {
+ if (this.restTemplate == null) {
+ char[] password = aaiProps.getCertPassword().toCharArray();
+ KeyStore ks = keyStore(aaiProps.getCert(), password);
+ SSLContextBuilder builder = SSLContextBuilder.create().loadKeyMaterial(ks, password);
+ SSLContext sslContext = builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
+ HttpClient client = HttpClients.custom().setSSLContext(sslContext).build();
+ RestTemplateBuilder restBld = aaiRestTempBuilder.additionalInterceptors(authInt);
+ this.restTemplate = restBld.requestFactory(new HttpComponentsClientHttpRequestFactory(client)).build();
+ }
+ return this.restTemplate;
+ }
+
+ KeyStore keyStore(String file, char[] password) throws Exception {
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
+ File key = ResourceUtils.getFile(file);
+ try (InputStream in = new FileInputStream(key)) {
+ keyStore.load(in, password);
+ }
+ return keyStore;
+ }
+}