Improve import and export VFC TOSCA attributes 71/118071/7
authorandre.schmid <andre.schmid@est.tech>
Tue, 2 Feb 2021 19:18:22 +0000 (19:18 +0000)
committerChristophe Closset <christophe.closset@intl.att.com>
Thu, 25 Feb 2021 12:20:17 +0000 (12:20 +0000)
Improve the import and export VFC TOSCA attributes, addressing the
following concerns:
- brings the import and export logic very close to the properties logic,
as they are very similar structures
- fix import/export default values for complex types and list of simple
or complex types
- fix export of unnecessary/empty attribute entries
- creation of attributes during the initialization (base types)
- inheritance of parent attributes

Change-Id: Ic733e3455fc256595b5c2b1f48e19a13be27b5cc
Issue-ID: SDC-3466
Signed-off-by: andre.schmid <andre.schmid@est.tech>
27 files changed:
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AttributeServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/AttributeConverter.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/PropertyConvertor.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/exception/ToscaConversionException.java [new file with mode: 0644]
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaAttribute.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaNodeType.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaProperty.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/ToscaSchemaDefinition.java [moved from catalog-be/src/main/java/org/openecomp/sdc/be/tosca/model/EntrySchema.java with 76% similarity]
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/utils/OutputConverter.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/AttributeConverterTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/EntrySchemaTest.java [deleted file]
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaAttributeTest.java [new file with mode: 0644]
catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyTest.java [deleted file]
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/jsongraph/JanusGraphDao.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/AttributeDefinition.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTypeOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/AttributeDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/JsonPresentationFields.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/tosca/ToscaDataDefinition.java
common-be/src/main/java/org/openecomp/sdc/be/utils/TypeUtils.java

index 614b261..ed26ead 100644 (file)
@@ -43,15 +43,14 @@ import java.util.function.Consumer;
 import java.util.function.Function;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringEscapeUtils;
+import org.onap.sdc.tosca.datatypes.model.EntrySchema;
 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
 import org.openecomp.sdc.be.config.BeEcompErrorManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.datatypes.elements.Annotation;
-import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
-import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.AnnotationTypeDefinition;
 import org.openecomp.sdc.be.model.AttributeDefinition;
@@ -182,7 +181,8 @@ public final class ImportUtils {
     }
 
     public enum ResultStatusEnum {
-        ELEMENT_NOT_FOUND, GENERAL_ERROR, OK, INVALID_PROPERTY_DEFAULT_VALUE, INVALID_PROPERTY_TYPE, INVALID_PROPERTY_VALUE, MISSING_ENTRY_SCHEMA_TYPE, INVALID_PROPERTY_NAME
+        ELEMENT_NOT_FOUND, GENERAL_ERROR, OK, INVALID_PROPERTY_DEFAULT_VALUE, INVALID_PROPERTY_TYPE,
+        INVALID_PROPERTY_VALUE, MISSING_ENTRY_SCHEMA_TYPE, INVALID_PROPERTY_NAME, INVALID_ATTRIBUTE_NAME
     }
 
     public enum ToscaElementTypeEnum {
@@ -422,7 +422,7 @@ public final class ImportUtils {
         setFieldBoolean(propertyValue, TypeUtils.ToscaTagNamesEnum.IS_PASSWORD,
             pass -> propertyDef.setPassword(Boolean.parseBoolean(pass)));
         setField(propertyValue, TypeUtils.ToscaTagNamesEnum.STATUS, propertyDef::setStatus);
-        setScheme(propertyValue, propertyDef);
+        setSchema(propertyValue, propertyDef);
         setPropertyConstraints(propertyValue, propertyDef);
 
         return propertyDef;
@@ -506,7 +506,7 @@ public final class ImportUtils {
         setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.HIDDEN, hidden -> inputDef.setHidden(Boolean.parseBoolean(hidden)));
         setFieldBoolean(inputValue, TypeUtils.ToscaTagNamesEnum.IMMUTABLE, immutable -> inputDef.setImmutable(Boolean.parseBoolean(immutable)));
 
-        setScheme(inputValue, inputDef);
+        setSchema(inputValue, inputDef);
         setPropertyConstraints(inputValue, inputDef);
         return inputDef;
     }
@@ -542,20 +542,27 @@ public final class ImportUtils {
         setJsonStringField(attributeMap, TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE, attributeDef.getType(),
             attributeDef::set_default);
 
-        setScheme(attributeMap, attributeDef);
+        setEntrySchema(attributeMap, attributeDef);
         return attributeDef;
     }
 
-    private static void setScheme(Map<String, Object> propertyValue,
-                                  ToscaDataDefinition toscaDataDefinition) {
-        Either<Object, ResultStatusEnum> schemaElementRes = findSchemaElement(propertyValue);
+    private static void setSchema(final Map<String, Object> propertyValue,
+                                  final PropertyDefinition propertyDefinition) {
+        final Either<Object, ResultStatusEnum> schemaElementRes = findEntrySchemaElement(propertyValue);
         if (schemaElementRes.isLeft()) {
-            SchemaDefinition schemaDef = getSchema(schemaElementRes.left().value());
-            toscaDataDefinition.setSchema(schemaDef);
+            propertyDefinition.setSchema(getSchema(schemaElementRes.left().value()));
         }
     }
 
-    private static Either<Object, ResultStatusEnum> findSchemaElement(Map<String, Object> propertyValue) {
+    private static void setEntrySchema(final Map<String, Object> toscaJsonMap,
+                                       final AttributeDefinition attributeDefinition) {
+        final Either<Object, ResultStatusEnum> schemaElementRes = findEntrySchemaElement(toscaJsonMap);
+        if (schemaElementRes.isLeft()) {
+            attributeDefinition.setEntry_schema(createEntrySchema(schemaElementRes.left().value()));
+        }
+    }
+
+    private static Either<Object, ResultStatusEnum> findEntrySchemaElement(final Map<String, Object> propertyValue) {
         return findToscaElement(propertyValue, TypeUtils.ToscaTagNamesEnum.ENTRY_SCHEMA, ToscaElementTypeEnum.ALL);
     }
 
@@ -573,6 +580,18 @@ public final class ImportUtils {
         return schema;
     }
 
+    private static EntrySchema createEntrySchema(final Object toscaEntrySchemaObj) {
+        final EntrySchema entrySchema = new EntrySchema();
+        if (toscaEntrySchemaObj instanceof String) {
+            entrySchema.setType((String) toscaEntrySchemaObj);
+        } else if (toscaEntrySchemaObj instanceof Map) {
+            final PropertyDefinition schemeProperty = createModuleProperty((Map<String, Object>) toscaEntrySchemaObj);
+            entrySchema.setType(schemeProperty.getType());
+            entrySchema.setDescription(schemeProperty.getDescription());
+        }
+        return entrySchema;
+    }
+
     private static void setField(Map<String, Object> toscaJson, TypeUtils.ToscaTagNamesEnum tagName,
                                  Consumer<String> setter) {
         Either<String, ResultStatusEnum> fieldStringValue = findFirstToscaStringElement(toscaJson, tagName);
@@ -600,6 +619,13 @@ public final class ImportUtils {
 
     }
 
+    public static Either<Map<String, AttributeDefinition>, ResultStatusEnum> getAttributes(final Map<String, Object> toscaJson) {
+        final Function<String, AttributeDefinition> elementGenByName = ImportUtils::createAttribute;
+        final Function<Map<String, Object>, AttributeDefinition> func = ImportUtils::createModuleAttribute;
+
+        return getElements(toscaJson, ToscaTagNamesEnum.ATTRIBUTES, elementGenByName, func);
+    }
+
     public static Either<Map<String, InputDefinition>, ResultStatusEnum> getInputs(Map<String, Object> toscaJson,
                                                                                    AnnotationTypeOperations annotationTypeOperations) {
         Function<String, InputDefinition> elementGenByName = ImportUtils::createInputs;
index 7e5e1b9..383d7cd 100644 (file)
@@ -353,6 +353,7 @@ public class ResourceImportManager {
             }
             setCapabilities(toscaJson, resource, parentResource);
             setProperties(toscaJson, resource);
+            setAttributes(toscaJson, resource);
             setRequirements(toscaJson, resource, parentResource);
             setInterfaceLifecycle(toscaJson, resource);
         } else {
@@ -537,6 +538,42 @@ public class ResourceImportManager {
         }
     }
 
+    private void setAttributes(final Map<String, Object> originalToscaJsonMap, final Resource resource) {
+        final Map<String, Object> toscaJsonMap = new HashMap<>(originalToscaJsonMap);
+        ImportUtils.removeElementFromJsonMap(toscaJsonMap, "capabilities");
+        final Either<Map<String, AttributeDefinition>, ResultStatusEnum> getAttributeEither = ImportUtils
+            .getAttributes(toscaJsonMap);
+
+        if (getAttributeEither.isRight()) {
+            final ResultStatusEnum resultStatus = getAttributeEither.right().value();
+            if (resultStatus == ResultStatusEnum.ELEMENT_NOT_FOUND) {
+                return;
+            }
+            throw new ByActionStatusComponentException(
+                componentsUtils.convertFromResultStatusEnum(resultStatus, JsonPresentationFields.ATTRIBUTES));
+        }
+
+        final List<AttributeDefinition> attributeDefinitionList = new ArrayList<>();
+        final Map<String, AttributeDefinition> attributeMap = getAttributeEither.left().value();
+        if (MapUtils.isEmpty(attributeMap)) {
+            return;
+        }
+        for (final Entry<String, AttributeDefinition> entry : attributeMap.entrySet()) {
+            final String name = entry.getKey();
+            if (!PROPERTY_NAME_PATTERN_IGNORE_LENGTH.matcher(name).matches()) {
+                log.debug("Detected attribute with invalid name '{}' during resource '{}' import. ",
+                    name, resource.getName());
+                throw new ByActionStatusComponentException(componentsUtils
+                    .convertFromResultStatusEnum(ResultStatusEnum.INVALID_ATTRIBUTE_NAME,
+                        JsonPresentationFields.ATTRIBUTES));
+            }
+            final AttributeDefinition attributeDefinition = entry.getValue();
+            attributeDefinition.setName(name);
+            attributeDefinitionList.add(attributeDefinition);
+        }
+        resource.setAttributes(attributeDefinitionList);
+    }
+
     private Resource setDerivedFrom(Map<String, Object> toscaJson, Resource resource) {
         Either<String, ResultStatusEnum> toscaDerivedFromElement = ImportUtils
             .findFirstToscaStringElement(toscaJson, TypeUtils.ToscaTagNamesEnum.DERIVED_FROM);
@@ -831,52 +868,12 @@ public class ResourceImportManager {
         final String payloadData = resourceMetaData.getPayloadData();
         if (payloadData != null) {
             resource.setToscaVersion(getToscaVersion(payloadData));
-            resource.setAttributes(getAttributes(payloadData));
         }
 
         final List<CategoryDefinition> categories = resourceMetaData.getCategories();
         calculateResourceIsAbstract(resource, categories);
     }
 
-    private List<AttributeDefinition> getAttributes(final String payloadData) {
-        final Map<String, Object> mappedToscaTemplate = decodePayload(payloadData);
-
-        final List<AttributeDefinition> attributeDataDefinitionList = new ArrayList<>();
-
-        final Either<Map<String, Object>, ResultStatusEnum> firstToscaMapElement = ImportUtils
-            .findFirstToscaMapElement(mappedToscaTemplate, ToscaTagNamesEnum.ATTRIBUTES);
-        if (firstToscaMapElement.isRight()) {
-            return attributeDataDefinitionList;
-        }
-        final Map<String, Object> attributes = firstToscaMapElement.left().value();
-
-        final Iterator<Entry<String, Object>> propertiesNameValue = attributes.entrySet().iterator();
-        while (propertiesNameValue.hasNext()) {
-            final Entry<String, Object> attributeNameValue = propertiesNameValue.next();
-            final Object value = attributeNameValue.getValue();
-            final String key = attributeNameValue.getKey();
-            if (value instanceof Map) {
-
-                final Map<String, Object> attributeMap = (Map<String, Object>) value;
-
-                final AttributeDefinition attributeDefinition = new AttributeDefinition();
-                attributeDefinition.setName(key);
-
-                setField(attributeMap, ToscaTagNamesEnum.DESCRIPTION, attributeDefinition::setDescription);
-                setField(attributeMap, ToscaTagNamesEnum.TYPE, attributeDefinition::setType);
-                setField(attributeMap, ToscaTagNamesEnum.DEFAULT_VALUE, attributeDefinition::set_default);
-                setField(attributeMap, ToscaTagNamesEnum.STATUS, attributeDefinition::setStatus);
-                setField(attributeMap, ToscaTagNamesEnum.ENTRY_SCHEMA, attributeDefinition::setSchema);
-                attributeDataDefinitionList.add(attributeDefinition);
-            } else {
-                final AttributeDefinition attributeDefinition = new AttributeDefinition();
-                attributeDefinition.setName(key);
-                attributeDataDefinitionList.add(attributeDefinition);
-            }
-        }
-        return attributeDataDefinitionList;
-    }
-
     private Map<String, Object> decodePayload(final String payloadData) {
         final String decodedPayload = new String(Base64.decodeBase64(payloadData));
         return (Map<String, Object>) new Yaml().load(decodedPayload);
index 8f1f2c1..98b3c84 100644 (file)
@@ -1384,6 +1384,9 @@ public class ComponentsUtils {
             case MISSING_ENTRY_SCHEMA_TYPE:
                 responseEnum = ActionStatus.INVALID_PROPERTY;
                 break;
+            case INVALID_ATTRIBUTE_NAME:
+                responseEnum = ActionStatus.INVALID_ATTRIBUTE;
+                break;
             default:
                 responseEnum = ActionStatus.GENERAL_ERROR;
                 break;
index a1500a4..2276273 100644 (file)
@@ -130,7 +130,8 @@ public class AttributeServlet extends AbstractValidationsServlet {
 
             if (errorWrapper.isEmpty()) {
                 AttributeBusinessLogic businessLogic = getClassFromWebAppContext(context, () -> AttributeBusinessLogic.class);
-                Either<AttributeDefinition, ResponseFormat> createAttribute = businessLogic.createAttribute(resourceId, attributeDataDefinition, userId);
+                Either<AttributeDefinition, ResponseFormat> createAttribute = businessLogic.
+                    createAttribute(resourceId, attributeDataDefinition, userId);
                 if (createAttribute.isRight()) {
                     errorWrapper.setInnerElement(createAttribute.right().value());
                 } else {
@@ -283,27 +284,6 @@ public class AttributeServlet extends AbstractValidationsServlet {
         }
     }
 
-    private void buildAttributeFromString(String data, Wrapper<AttributeDataDefinition> attributesWrapper,
-                                          Wrapper<ResponseFormat> errorWrapper) {
-        try {
-            Gson gson = new GsonBuilder().setPrettyPrinting().create();
-            final AttributeDataDefinition attribute = gson.fromJson(data, AttributeDataDefinition.class);
-            if (attribute == null) {
-                log.info(ATTRIBUTE_CONTENT_IS_INVALID, data);
-                ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
-                errorWrapper.setInnerElement(responseFormat);
-            } else {
-                attributesWrapper.setInnerElement(attribute);
-            }
-
-        } catch (Exception e) {
-            ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
-            errorWrapper.setInnerElement(responseFormat);
-            log.debug(ATTRIBUTE_CONTENT_IS_INVALID, data, e);
-            log.info(ATTRIBUTE_CONTENT_IS_INVALID, data);
-        }
-    }
-
     private AttributeDefinition convertJsonToObject(final String data,
                                                     final Wrapper<ResponseFormat> errorWrapper) {
 
index 085c075..a0f8d8b 100644 (file)
@@ -21,6 +21,7 @@ package org.openecomp.sdc.be.tosca;
 
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
 import com.google.gson.JsonParser;
 import com.google.gson.stream.JsonReader;
 import java.io.StringReader;
@@ -32,7 +33,10 @@ import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
 import org.openecomp.sdc.be.model.tosca.converters.DataTypePropertyConverter;
 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
+import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
+import org.openecomp.sdc.be.tosca.model.ToscaSchemaDefinition;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
 import org.springframework.beans.factory.config.BeanDefinition;
@@ -61,15 +65,16 @@ public class AttributeConverter {
     }
 
     /**
-     * Converts and {@link AttributeDefinition} to a {@link ToscaAttribute}.
+     * Converts an {@link AttributeDefinition} to a {@link ToscaAttribute}.
      *
      * @param attributeDefinition the attribute definition to be converted
      * @return the {@link ToscaAttribute} instance based on the the given {@link AttributeDefinition} instance
      */
-    public ToscaAttribute convert(final AttributeDefinition attributeDefinition) {
+    public ToscaAttribute convert(final AttributeDefinition attributeDefinition) throws ToscaConversionException {
         final ToscaAttribute toscaAttribute = new ToscaAttribute();
         LOGGER.trace("Converting attribute '{}' from type '{}' with default value '{}'",
             attributeDefinition.getName(), attributeDefinition.getType(), attributeDefinition.getDefaultValue());
+        toscaAttribute.setEntrySchema(convert(attributeDefinition.getEntry_schema()));
         toscaAttribute.setType(attributeDefinition.getType());
         toscaAttribute.setDescription(attributeDefinition.getDescription());
         toscaAttribute.setStatus(attributeDefinition.getStatus());
@@ -87,8 +92,19 @@ public class AttributeConverter {
         return toscaAttribute;
     }
 
+    private ToscaSchemaDefinition convert(final EntrySchema entrySchema) {
+        if (entrySchema == null) {
+            return null;
+        }
+
+        final ToscaSchemaDefinition toscaSchemaDefinition = new ToscaSchemaDefinition();
+        toscaSchemaDefinition.setType(entrySchema.getType());
+        toscaSchemaDefinition.setDescription(entrySchema.getDescription());
+        return toscaSchemaDefinition;
+    }
+
     private Object convertToToscaObject(final String name, final String attributeType, String value,
-                                        final EntrySchema schemaDefinition, final boolean preserveEmptyValue) {
+                                        final EntrySchema schemaDefinition, final boolean preserveEmptyValue) throws ToscaConversionException {
         final String innerType = schemaDefinition == null ? attributeType : schemaDefinition.getType();
         LOGGER.trace("Converting attribute '{}' of type '{}', value '{}', innerType '{}'",
             name, attributeType, value, innerType);
@@ -114,12 +130,10 @@ public class AttributeConverter {
                 isScalar = ToscaPropertyType.getTypeIfScalar(predefinedType.getType()) != null;
             }
             final JsonElement valueAsJson = parseToJson(value);
-            if (valueAsJson.isJsonObject()) {
-                final JsonObject jsonObj = valueAsJson.getAsJsonObject();
-                if (jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_ATTRIBUTE.getFunctionName())) {
-                    return ToscaMapValueConverter.getInstance().handleComplexJsonValue(valueAsJson);
-                }
+            if (isValueGetAttribute(valueAsJson)) {
+                return ToscaMapValueConverter.getInstance().handleComplexJsonValue(valueAsJson.getAsJsonObject());
             }
+
             //if it has a converter
             if (predefinedType != null && predefinedType.getValueConverter() != null) {
                 LOGGER.trace("It's well defined type. convert it");
@@ -134,9 +148,16 @@ public class AttributeConverter {
             return toscaMapValueConverter.convertDataTypeToToscaObject(
                 innerType, dataTypes, null, false, valueAsJson, preserveEmptyValue);
 
+        } catch (final JsonParseException e) {
+            final String errorMsg = "Failed to parse json value";
+            LOGGER.error(EcompLoggerErrorCode.SCHEMA_ERROR, "Attribute Converter",
+                errorMsg, e);
+            throw new ToscaConversionException(errorMsg, e);
         } catch (final Exception e) {
-            LOGGER.debug("convertToToscaValue failed to parse json value :", e);
-            return null;
+            final String errorMsg = "Unexpected error occurred while converting attribute value to TOSCA";
+            LOGGER.error(EcompLoggerErrorCode.UNKNOWN_ERROR, "Attribute Converter",
+                errorMsg, e);
+            throw new ToscaConversionException(errorMsg, e);
         }
 
     }
@@ -148,8 +169,16 @@ public class AttributeConverter {
         return new JsonParser().parse(jsonReader);
     }
 
+    private boolean isValueGetAttribute(final JsonElement valueAsJson) {
+        if (!valueAsJson.isJsonObject()) {
+            return false;
+        }
+        final JsonObject jsonObj = valueAsJson.getAsJsonObject();
+        return jsonObj.entrySet().size() == 1 && jsonObj.has(ToscaFunctions.GET_ATTRIBUTE.getFunctionName());
+    }
+
     private String getTypeDefaultValue(final String attributeType) {
         return DataTypePropertyConverter.getInstance().getDataTypePropertiesDefaultValuesRec(attributeType, dataTypes);
     }
 
-}
\ No newline at end of file
+}
index 4c4f19b..59b859d 100644 (file)
@@ -44,7 +44,7 @@ import org.openecomp.sdc.be.model.tosca.converters.DataTypePropertyConverter;
 import org.openecomp.sdc.be.model.tosca.converters.ToscaMapValueConverter;
 import org.openecomp.sdc.be.model.tosca.converters.ToscaValueBaseConverter;
 import org.openecomp.sdc.be.model.tosca.converters.ToscaValueConverter;
-import org.openecomp.sdc.be.tosca.model.EntrySchema;
+import org.openecomp.sdc.be.tosca.model.ToscaSchemaDefinition;
 import org.openecomp.sdc.be.tosca.model.ToscaNodeType;
 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
 import org.openecomp.sdc.common.log.wrappers.Logger;
@@ -86,10 +86,10 @@ public class PropertyConvertor {
         log.trace("try to convert property {} from type {} with default value [{}]", property.getName(), property.getType(), property.getDefaultValue());
         SchemaDefinition schema = property.getSchema();
         if (schema != null && schema.getProperty() != null && schema.getProperty().getType() != null && !schema.getProperty().getType().isEmpty()) {
-            EntrySchema eschema = new EntrySchema();
-            eschema.setType(schema.getProperty().getType());
-            eschema.setDescription(schema.getProperty().getDescription());
-            prop.setEntry_schema(eschema);
+            final ToscaSchemaDefinition toscaSchemaDefinition = new ToscaSchemaDefinition();
+            toscaSchemaDefinition.setType(schema.getProperty().getType());
+            toscaSchemaDefinition.setDescription(schema.getProperty().getDescription());
+            prop.setEntry_schema(toscaSchemaDefinition);
         }
         String defaultValue = property.getDefaultValue();
         if(Objects.isNull(defaultValue)) {
index 0459b5d..1f0270f 100644 (file)
@@ -28,9 +28,7 @@ import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
 import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import fj.data.Either;
-import java.beans.IntrospectionException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -102,9 +100,11 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
 import org.openecomp.sdc.be.tosca.PropertyConvertor.PropertyType;
 import org.openecomp.sdc.be.tosca.builder.ToscaRelationshipBuilder;
+import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
 import org.openecomp.sdc.be.tosca.model.CapabilityFilter;
 import org.openecomp.sdc.be.tosca.model.NodeFilter;
 import org.openecomp.sdc.be.tosca.model.SubstitutionMapping;
+import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
 import org.openecomp.sdc.be.tosca.model.ToscaCapability;
 import org.openecomp.sdc.be.tosca.model.ToscaDataType;
 import org.openecomp.sdc.be.tosca.model.ToscaGroupTemplate;
@@ -122,6 +122,7 @@ import org.openecomp.sdc.be.tosca.model.ToscaTopolgyTemplate;
 import org.openecomp.sdc.be.tosca.utils.ForwardingPathToscaUtil;
 import org.openecomp.sdc.be.tosca.utils.InputConverter;
 import org.openecomp.sdc.be.tosca.utils.OutputConverter;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.yaml.snakeyaml.DumperOptions;
@@ -324,7 +325,15 @@ public class ToscaExportHandler {
             topologyTemplate.setInputs(inputs);
         }
 
-        final Map<String, ToscaProperty> outputs = outputConverter.convert(component.getOutputs(), dataTypes);
+        final Map<String, ToscaProperty> outputs;
+        try {
+            outputs = outputConverter.convert(component.getOutputs(), dataTypes);
+        } catch (final ToscaConversionException e) {
+            log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
+                "Could not parse component '{}' outputs. Component unique id '{}'.",
+                new Object[]{component.getName(), component.getUniqueId(), e});
+            return Either.right(ToscaError.GENERAL_ERROR);
+        }
         if (!outputs.isEmpty()) {
             topologyTemplate.setOutputs(outputs);
         }
@@ -748,6 +757,18 @@ public class ToscaExportHandler {
             .addInterfaceDefinitionElement(component, toscaNodeType, dataTypes, isAssociatedComponent);
         addInputsToProperties(dataTypes, inputDef, mergedProperties);
 
+        final Map<String, ToscaAttribute> toscaAttributeMap;
+        try {
+            toscaAttributeMap = convertToToscaAttributes(component.getAttributes(), dataTypes);
+        } catch (final ToscaConversionException e) {
+            log.error(EcompLoggerErrorCode.SCHEMA_ERROR, ToscaExportHandler.class.getName(),
+                "Could not parse component '{}' attributes. Component unique id '{}'.",
+                new Object[]{component.getName(), component.getUniqueId(), e});
+            return Either.right(ToscaError.GENERAL_ERROR);
+        }
+        if (!toscaAttributeMap.isEmpty()) {
+            toscaNodeType.setAttributes(toscaAttributeMap);
+        }
         if (CollectionUtils.isNotEmpty(component.getProperties())) {
             List<PropertyDefinition> properties = component.getProperties();
             Map<String, ToscaProperty> convertedProperties = properties.stream()
@@ -790,6 +811,19 @@ public class ToscaExportHandler {
         return convertReqCapAndTypeName(componentsCache, component, toscaNode, nodeTypes, toscaNodeType, dataTypes);
     }
 
+    private Map<String, ToscaAttribute> convertToToscaAttributes(final List<AttributeDefinition> attributeList,
+                                                                 final Map<String, DataTypeDefinition> dataTypes) throws ToscaConversionException {
+        if (CollectionUtils.isEmpty(attributeList)) {
+            return Collections.emptyMap();
+        }
+        final AttributeConverter attributeConverter = new AttributeConverter(dataTypes);
+        final Map<String, ToscaAttribute> toscaAttributeMap = new HashMap<>();
+        for (final AttributeDefinition attributeDefinition : attributeList) {
+            toscaAttributeMap.put(attributeDefinition.getName(), attributeConverter.convert(attributeDefinition));
+        }
+        return toscaAttributeMap;
+    }
+
     private Either<ToscaTemplate, ToscaError> convertReqCapAndTypeName(Map<String, Component> componentsCache,
                                                                        Component component, ToscaTemplate toscaNode,
                                                                        Map<String, ToscaNodeType> nodeTypes,
@@ -1050,31 +1084,9 @@ public class ToscaExportHandler {
                 : NATIVE_ROOT;
             toscaNodeType.setDerived_from(derivedFrom);
         }
-        if (component instanceof Resource) {
-            final List<AttributeDefinition> attributes = ((Resource) component).getAttributes();
-            if (CollectionUtils.isNotEmpty(attributes)) {
-                final Map<String, Object> attributeDataDefinitionMap = new HashMap<>();
-                attributes.forEach(attributeDataDefinition ->
-                    buildAttributeData(attributeDataDefinition, attributeDataDefinitionMap));
-
-                toscaNodeType.setAttributes(attributeDataDefinitionMap);
-            }
-        }
         return toscaNodeType;
     }
 
-    private void buildAttributeData(final AttributeDefinition originalAttributeDefinition,
-                                    final Map<String, Object> attributeDataDefinitionMap) {
-
-        attributeDataDefinitionMap.put(originalAttributeDefinition.getName(),
-            new ObjectMapper().convertValue(new org.onap.sdc.tosca.datatypes.model.AttributeDefinition(
-                originalAttributeDefinition.getType(),
-                originalAttributeDefinition.getDescription(),
-                originalAttributeDefinition.get_default(),
-                originalAttributeDefinition.getStatus(),
-                originalAttributeDefinition.getEntry_schema()), Object.class));
-    }
-
     private Either<Map<String, Object>, ToscaError> createProxyInterfaceTypes(Component container) {
 
         Map<String, Object> proxyInterfaceTypes = new HashMap<>();
@@ -1679,12 +1691,22 @@ public class ToscaExportHandler {
         CustomRepresenter() {
             super();
             this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
+            this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
             // null representer is exceptional and it is stored as an instance
             // variable.
             this.nullRepresenter = new RepresentNull();
 
         }
 
+        private class RepresentToscaAttribute implements Represent {
+
+            @Override
+            public Node representData(Object data) {
+                final ToscaAttribute toscaAttribute = (ToscaAttribute) data;
+                return represent(toscaAttribute.asToscaMap());
+            }
+        }
+
         private class RepresentToscaPropertyAssignment implements Represent {
 
             public Node representData(Object data) {
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/exception/ToscaConversionException.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/exception/ToscaConversionException.java
new file mode 100644 (file)
index 0000000..2d37a35
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.tosca.exception;
+
+public class ToscaConversionException extends Exception {
+
+    public ToscaConversionException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
index 891347d..ea56e60 100644 (file)
 
 package org.openecomp.sdc.be.tosca.model;
 
+import java.util.LinkedHashMap;
+import java.util.Map;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
+import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
 
 /**
  * Represents a TOSCA Attribute Definition (see TOSCA 1.3, Section 3.6.12 Attribute definition)
@@ -42,6 +45,12 @@ public class ToscaAttribute {
     private String description;
     @Getter
     @Setter
+    private ToscaSchemaDefinition keySchema;
+    @Getter
+    @Setter
+    private ToscaSchemaDefinition entrySchema;
+    @Getter
+    @Setter
     private String status;
 
     public Object getDefault() {
@@ -52,4 +61,33 @@ public class ToscaAttribute {
         this.defaultValue = defaultValue;
     }
 
+    /**
+     * Converts this object to Map, ignoring null fields. The entries of the map are based on the TOSCA Attribute Definition.
+     *
+     * @return a Map representing the TOSCA Attribute Definition.
+     */
+    public Map<String, Object> asToscaMap() {
+        final Map<String, Object> toscaAttributeAsMap = new LinkedHashMap<>();
+        if (getType() != null) {
+            toscaAttributeAsMap.put(ToscaTagNamesEnum.TYPE.getElementName(), getType());
+        }
+        if (getDescription() != null) {
+            toscaAttributeAsMap.put(ToscaTagNamesEnum.DESCRIPTION.getElementName(), getDescription());
+        }
+        if (getKeySchema() != null) {
+            toscaAttributeAsMap.put(ToscaTagNamesEnum.KEY_SCHEMA.getElementName(), getKeySchema());
+        }
+        if (getEntrySchema() != null) {
+            toscaAttributeAsMap.put(ToscaTagNamesEnum.ENTRY_SCHEMA.getElementName(), getEntrySchema());
+        }
+        if (getDefault() != null) {
+            toscaAttributeAsMap.put(ToscaTagNamesEnum.DEFAULT.getElementName(), getDefault());
+        }
+        if (getStatus() != null) {
+            toscaAttributeAsMap.put(ToscaTagNamesEnum.STATUS.getElementName(), getStatus());
+        }
+
+        return toscaAttributeAsMap;
+    }
+
 }
index 856c430..c43486f 100644 (file)
@@ -40,6 +40,6 @@ public class ToscaNodeType {
     private Map<String, ToscaCapability> capabilities;
 
     private List<Map<String, ToscaRequirement>> requirements;
-    private Map<String, Object> attributes;
+    private Map<String, ToscaAttribute> attributes;
 
 }
index 7ebb2cb..fb5c544 100644 (file)
@@ -44,7 +44,7 @@ public class ToscaProperty {
     private Boolean required;
     @Getter
     @Setter
-    private EntrySchema entry_schema;
+    private ToscaSchemaDefinition entry_schema;
     @Getter
     @Setter
     private List<ToscaPropertyConstraint> constraints;
 
 package org.openecomp.sdc.be.tosca.model;
 
-public class EntrySchema {
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ToscaSchemaDefinition {
     private String type;
     private String description;
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
 }
index 85400a7..1e7fc81 100644 (file)
@@ -27,6 +27,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.OutputDefinition;
 import org.openecomp.sdc.be.tosca.AttributeConverter;
+import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
 import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
 import org.openecomp.sdc.be.tosca.model.ToscaOutput;
 import org.openecomp.sdc.be.tosca.model.ToscaProperty;
@@ -45,17 +46,17 @@ public class OutputConverter {
     }
 
     public Map<String, ToscaProperty> convert(final List<OutputDefinition> outputDefinitionList,
-                                              final Map<String, DataTypeDefinition> dataTypes) {
+                                              final Map<String, DataTypeDefinition> dataTypes) throws ToscaConversionException {
         final AttributeConverter attributeConverter = this.attributeConverterProvider.getObject(dataTypes);
         final Map<String, ToscaProperty> outputMap = new HashMap<>();
         if (CollectionUtils.isEmpty(outputDefinitionList)) {
             return Collections.emptyMap();
         }
-        outputDefinitionList.forEach(outputDefinition -> {
+        for (final OutputDefinition outputDefinition : outputDefinitionList) {
             final ToscaAttribute toscaAttribute = attributeConverter.convert(outputDefinition);
             final ToscaProperty toscaProperty = new ToscaOutput(toscaAttribute);
             outputMap.put(outputDefinition.getName(), toscaProperty);
-        });
+        }
         return outputMap;
     }
 }
index 456074f..891d2c8 100644 (file)
@@ -1265,8 +1265,6 @@ class ComponentInstanceBusinessLogicTest {
         ComponentInstanceAttribute attribute = new ComponentInstanceAttribute();
         attribute.setType("string");
         attribute.setUniqueId("testCreateOrUpdateAttributeValueForCopyPaste");
-        SchemaDefinition def = Mockito.mock(SchemaDefinition.class);
-        attribute.setSchema(def);
         LifecycleStateEnum oldLifeCycleState = service.getLifecycleState();
         String oldLastUpdatedUserId = service.getLastUpdaterUserId();
         service.setLastUpdaterUserId(USER_ID);
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/AttributeConverterTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/AttributeConverterTest.java
new file mode 100644 (file)
index 0000000..8292568
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.tosca;
+
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.onap.sdc.tosca.datatypes.model.EntrySchema;
+import org.openecomp.sdc.be.model.AttributeDefinition;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
+import org.openecomp.sdc.be.tosca.exception.ToscaConversionException;
+import org.openecomp.sdc.be.tosca.model.ToscaAttribute;
+
+class AttributeConverterTest {
+
+    @Test
+    void testScalarTypeConversion() throws ToscaConversionException {
+        //given
+        final AttributeConverter attributeConverter = new AttributeConverter(Collections.emptyMap());
+        final AttributeDefinition attributeDefinition = new AttributeDefinition();
+        attributeDefinition.setType(ToscaPropertyType.STRING.getType());
+        attributeDefinition.setDescription("aDescription");
+        attributeDefinition.setStatus("aStatus");
+        attributeDefinition.setDefaultValue("aDefaultValue");
+        //when
+        final ToscaAttribute actualToscaAttribute = attributeConverter.convert(attributeDefinition);
+        //then
+        assertAttribute(attributeDefinition, actualToscaAttribute);
+    }
+
+    @Test
+    void testScalarNoDefaultValueConversion() throws ToscaConversionException {
+        //given
+        final AttributeConverter attributeConverter = new AttributeConverter(Collections.emptyMap());
+        final AttributeDefinition attributeDefinition = new AttributeDefinition();
+        attributeDefinition.setType(ToscaPropertyType.STRING.getType());
+        attributeDefinition.setDescription("aDescription");
+        attributeDefinition.setStatus("aStatus");
+        //when
+        final ToscaAttribute actualToscaAttribute = attributeConverter.convert(attributeDefinition);
+        //then
+        assertAttribute(attributeDefinition, null, actualToscaAttribute);
+    }
+
+    @Test
+    void testListTypeConversion() throws JsonProcessingException, ToscaConversionException {
+        //given
+        final Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
+        final AttributeConverter attributeConverter = new AttributeConverter(dataTypes);
+        final AttributeDefinition attributeDefinition = new AttributeDefinition();
+        attributeDefinition.setType(ToscaPropertyType.LIST.getType());
+        attributeDefinition.setDescription("aDescription");
+        attributeDefinition.setStatus("aStatus");
+        final EntrySchema entrySchema = new EntrySchema();
+        entrySchema.setDescription("anEntrySchemaDescription");
+        entrySchema.setType(ToscaPropertyType.LIST.getType());
+        attributeDefinition.setEntry_schema(entrySchema);
+        final List<String> defaultValueList = new ArrayList<>();
+        defaultValueList.add("entry1");
+        defaultValueList.add("entry2");
+        defaultValueList.add("entry2");
+        attributeDefinition.setDefaultValue(parseToJsonString(defaultValueList));
+        //when
+        final ToscaAttribute actualToscaAttribute = attributeConverter.convert(attributeDefinition);
+        //then
+        assertAttribute(attributeDefinition, defaultValueList, actualToscaAttribute);
+    }
+
+    @Test
+    void testDataTypeTypeConversion() throws JsonProcessingException, ToscaConversionException {
+        //given
+        final Map<String, DataTypeDefinition> dataTypes = new HashMap<>();
+        final DataTypeDefinition dataTypeDefinition = new DataTypeDefinition();
+        final List<PropertyDefinition> propertyDefinitionList = new ArrayList<>();
+        final PropertyDefinition integerProperty = new PropertyDefinition();
+        integerProperty.setName("anIntegerProperty");
+        integerProperty.setType(ToscaPropertyType.INTEGER.getType());
+        propertyDefinitionList.add(integerProperty);
+        final PropertyDefinition stringProperty = new PropertyDefinition();
+        stringProperty.setName("aStringProperty");
+        stringProperty.setType(ToscaPropertyType.STRING.getType());
+        propertyDefinitionList.add(stringProperty);
+        dataTypeDefinition.setProperties(propertyDefinitionList);
+        final String myDataType = "com.data.type.my";
+        dataTypeDefinition.setType(myDataType);
+        dataTypes.put(myDataType, dataTypeDefinition);
+
+        final AttributeConverter attributeConverter = new AttributeConverter(dataTypes);
+        final AttributeDefinition attributeDefinition = new AttributeDefinition();
+        attributeDefinition.setType(myDataType);
+        attributeDefinition.setDescription("aDescription");
+        attributeDefinition.setStatus("aStatus");
+        final Map<String, Object> defaultValueMap = new HashMap<>();
+        defaultValueMap.put("aStringProperty", "aStringPropertyValue");
+        defaultValueMap.put("anIntegerProperty", 0);
+        final String defaultValue = parseToJsonString(defaultValueMap);
+        attributeDefinition.setDefaultValue(defaultValue);
+        //when
+        final ToscaAttribute actualToscaAttribute = attributeConverter.convert(attributeDefinition);
+        //then
+        assertAttribute(attributeDefinition, defaultValueMap, actualToscaAttribute);
+    }
+
+
+    @Test
+    void testInvalidDefaultValueJsonConversion() {
+        //given
+        final AttributeConverter attributeConverter = new AttributeConverter(Collections.emptyMap());
+        final AttributeDefinition attributeDefinition = new AttributeDefinition();
+        attributeDefinition.setDefaultValue(": thisIsAnInvalidJson");
+        //when, then
+        final ToscaConversionException toscaConversionException = assertThrows(ToscaConversionException.class,
+            () -> attributeConverter.convert(attributeDefinition));
+        assertEquals("Failed to parse json value", toscaConversionException.getMessage());
+    }
+
+    private void assertAttribute(final AttributeDefinition expectedAttributeDefinition,
+                                 final ToscaAttribute actualToscaAttribute) {
+        assertAttribute(expectedAttributeDefinition, expectedAttributeDefinition.get_default(), actualToscaAttribute);
+    }
+
+    private void assertAttribute(final AttributeDefinition expectedAttributeDefinition, final Object expectedDefault,
+                                 final ToscaAttribute actualToscaAttribute) {
+        assertEquals(expectedAttributeDefinition.getType(), actualToscaAttribute.getType());
+        assertEquals(expectedAttributeDefinition.getDescription(), actualToscaAttribute.getDescription());
+        assertEquals(expectedAttributeDefinition.getStatus(), actualToscaAttribute.getStatus());
+        if (expectedAttributeDefinition.getEntry_schema() == null) {
+            assertNull(actualToscaAttribute.getEntrySchema());
+        } else {
+            assertEquals(expectedAttributeDefinition.getEntry_schema().getType(),
+                actualToscaAttribute.getEntrySchema().getType());
+            assertEquals(
+                expectedAttributeDefinition.getEntry_schema().getDescription(),
+                actualToscaAttribute.getEntrySchema().getDescription());
+        }
+        assertEquals(expectedDefault, actualToscaAttribute.getDefault());
+    }
+
+    private String parseToJsonString(final Object value) throws JsonProcessingException {
+        final ObjectMapper objectMapper = new ObjectMapper();
+        return objectMapper.writeValueAsString(value);
+    }
+
+}
\ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/EntrySchemaTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/EntrySchemaTest.java
deleted file mode 100644 (file)
index dc29602..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2019 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.sdc.be.tosca.model;
-
-import org.junit.Test;
-
-
-public class EntrySchemaTest {
-
-       private EntrySchema createTestSubject() {
-               return new EntrySchema();
-       }
-
-       
-       @Test
-       public void testGetType() throws Exception {
-               EntrySchema testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getType();
-       }
-
-       
-       @Test
-       public void testSetType() throws Exception {
-               EntrySchema testSubject;
-               String type = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setType(type);
-       }
-
-       
-       @Test
-       public void testGetDescription() throws Exception {
-               EntrySchema testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getDescription();
-       }
-
-       
-       @Test
-       public void testSetDescription() throws Exception {
-               EntrySchema testSubject;
-               String description = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setDescription(description);
-       }
-}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaAttributeTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaAttributeTest.java
new file mode 100644 (file)
index 0000000..2473865
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation
+ *  ================================================================================
+ *  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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.tosca.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DESCRIPTION;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ENTRY_SCHEMA;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.KEY_SCHEMA;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.STATUS;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TYPE;
+
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+
+class ToscaAttributeTest {
+
+    @Test
+    void testMapConversion() {
+        final ToscaAttribute toscaAttribute = new ToscaAttribute();
+        assertToscaAttributeMap(toscaAttribute);
+
+        toscaAttribute.setType("type");
+        toscaAttribute.setDescription("description");
+        toscaAttribute.setKeySchema(new ToscaSchemaDefinition());
+        toscaAttribute.setEntrySchema(new ToscaSchemaDefinition());
+        toscaAttribute.setDefault("default");
+        toscaAttribute.setStatus("status");
+
+        assertToscaAttributeMap(toscaAttribute);
+    }
+
+    private void assertToscaAttributeMap(final ToscaAttribute toscaAttribute) {
+        final Map<String, Object> toscaAttributeAsMap = toscaAttribute.asToscaMap();
+        assertEquals(toscaAttribute.getType(), toscaAttributeAsMap.get(TYPE.getElementName()));
+        assertEquals(toscaAttribute.getDescription(),
+            toscaAttributeAsMap.get(DESCRIPTION.getElementName()));
+        assertEquals(toscaAttribute.getKeySchema(),
+            toscaAttributeAsMap.get(KEY_SCHEMA.getElementName()));
+        assertEquals(toscaAttribute.getEntrySchema(),
+            toscaAttributeAsMap.get(ENTRY_SCHEMA.getElementName()));
+        assertEquals(toscaAttribute.getDefault(), toscaAttributeAsMap.get(DEFAULT.getElementName()));
+        assertEquals(toscaAttribute.getStatus(), toscaAttributeAsMap.get(STATUS.getElementName()));
+    }
+}
\ No newline at end of file
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/model/ToscaPropertyTest.java
deleted file mode 100644 (file)
index 19b5dd3..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2019 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.sdc.be.tosca.model;
-
-import org.junit.Test;
-
-
-public class ToscaPropertyTest {
-
-       private ToscaProperty createTestSubject() {
-               return new ToscaProperty();
-       }
-
-       
-       @Test
-       public void testGetEntry_schema() throws Exception {
-               ToscaProperty testSubject;
-               EntrySchema result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getEntry_schema();
-       }
-
-       
-       @Test
-       public void testSetEntry_schema() throws Exception {
-               ToscaProperty testSubject;
-               EntrySchema entry_schema = null;
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setEntry_schema(entry_schema);
-       }
-
-       
-       @Test
-       public void testGetType() throws Exception {
-               ToscaProperty testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getType();
-       }
-
-       
-       @Test
-       public void testSetType() throws Exception {
-               ToscaProperty testSubject;
-               String type = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setType(type);
-       }
-
-       
-       @Test
-       public void testGetDefaultp() throws Exception {
-               ToscaProperty testSubject;
-               Object result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getDefaultp();
-       }
-
-       
-       @Test
-       public void testSetDefaultp() throws Exception {
-               ToscaProperty testSubject;
-               Object defaultp = null;
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setDefaultp(defaultp);
-       }
-
-       
-       @Test
-       public void testGetDescription() throws Exception {
-               ToscaProperty testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getDescription();
-       }
-
-       
-       @Test
-       public void testSetDescription() throws Exception {
-               ToscaProperty testSubject;
-               String description = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setDescription(description);
-       }
-
-       
-       @Test
-       public void testGetRequired() throws Exception {
-               ToscaProperty testSubject;
-               Boolean result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getRequired();
-       }
-
-       
-       @Test
-       public void testSetRequired() throws Exception {
-               ToscaProperty testSubject;
-               Boolean required = null;
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setRequired(required);
-       }
-
-       
-       @Test
-       public void testGetStatus() throws Exception {
-               ToscaProperty testSubject;
-               String result;
-
-               // default test
-               testSubject = createTestSubject();
-               result = testSubject.getStatus();
-       }
-
-       
-       @Test
-       public void testSetStatus() throws Exception {
-               ToscaProperty testSubject;
-               String status = "";
-
-               // default test
-               testSubject = createTestSubject();
-               testSubject.setStatus(status);
-       }
-}
index aceaf95..ea38b93 100644 (file)
@@ -55,7 +55,7 @@ public enum ActionStatus {
     // Property related
     PROPERTY_ALREADY_EXIST, PROPERTY_NAME_ALREADY_EXISTS, PROPERTY_NOT_FOUND, INVALID_PROPERTY, INVALID_PROPERTY_TYPE, INVALID_PROPERTY_INNER_TYPE, MISSING_PROPERTY_NAME, MISSING_PROPERTY_VALUE,
     // Attribute related
-    ATTRIBUTE_ALREADY_EXIST, ATTRIBUTE_NOT_FOUND,
+    ATTRIBUTE_ALREADY_EXIST, ATTRIBUTE_NOT_FOUND, INVALID_ATTRIBUTE,
     // State related
     INVALID_SERVICE_STATE, COMPONENT_IN_CHECKOUT_STATE, ILLEGAL_COMPONENT_STATE, COMPONENT_IN_CERT_IN_PROGRESS_STATE, COMPONENT_SENT_FOR_CERTIFICATION, COMPONENT_VERSION_ALREADY_EXIST, COMPONENT_ALREADY_CHECKED_IN, COMPONENT_CHECKOUT_BY_ANOTHER_USER, COMPONENT_IN_USE, COMPONENT_HAS_NEWER_VERSION, COMPONENT_ALREADY_CERTIFIED, COMPONENT_NOT_READY_FOR_CERTIFICATION, COMPONENT_ARTIFACT_NOT_FOUND, COMPONENT_INSTANCE_NOT_FOUND, COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, SERVICE_NOT_FOUND, SERVICE_CATEGORY_CANNOT_BE_CHANGED, SERVICE_NAME_CANNOT_BE_CHANGED, SERVICE_ICON_CANNOT_BE_CHANGED, COMPONENT_TOO_MUCH_CATEGORIES, SERVICE_CANNOT_CONTAIN_SUBCATEGORY, RESOURCE_CATEGORY_CANNOT_BE_CHANGED, RESOURCE_NAME_CANNOT_BE_CHANGED, RESOURCE_ICON_CANNOT_BE_CHANGED, RESOURCE_VENDOR_NAME_CANNOT_BE_CHANGED, RESOURCE_TOO_MUCH_SUBCATEGORIES, SERVICE_ICON_EXCEEDS_LIMIT, RESOURCE_INSTANCE_NOT_FOUND, RESOURCE_INSTANCE_BAD_REQUEST, RESOURCE_INSTANCE_MATCH_NOT_FOUND, RESOURCE_INSTANCE_ALREADY_EXIST, RESOURCE_INSTANCE_RELATION_NOT_FOUND, COMPONENT_MISSING_SUBCATEGORY, COMPONENT_INVALID_SUBCATEGORY, ARTIFACT_TYPE_NOT_SUPPORTED, MISSING_ARTIFACT_TYPE, ARTIFACT_LOGICAL_NAME_CANNOT_BE_CHANGED, ARTIFACT_EXIST, ARTIFACT_NOT_FOUND, ARTIFACT_INVALID_MD5, MISSING_ARTIFACT_NAME, MISSING_PROJECT_CODE, INVALID_PROJECT_CODE, COMPONENT_MISSING_MANDATORY_ARTIFACTS, LIFECYCLE_TYPE_ALREADY_EXIST, SERVICE_NOT_AVAILABLE_FOR_DISTRIBUTION, MISSING_LIFECYCLE_TYPE, RESOURCE_VFCMT_LIFECYCLE_STATE_NOT_VALID,
     // Distribution
@@ -190,5 +190,4 @@ public enum ActionStatus {
 
     //Abstract template related
     ABSTRACT, NORMAL
-       ;
     }
index be1dc45..bda3709 100644 (file)
@@ -39,6 +39,7 @@ import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
 import org.openecomp.sdc.common.jsongraph.util.CommonUtility;
 import org.openecomp.sdc.common.jsongraph.util.CommonUtility.LogLevelEnum;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.springframework.beans.factory.annotation.Qualifier;
 
@@ -94,11 +95,12 @@ public class JanusGraphDao {
                 return Either.left(graphVertex);
 
             } catch (Exception e) {
-                logger.debug("Failed to create Node for ID [{}]", graphVertex.getUniqueId(), e);
+                logger.error(EcompLoggerErrorCode.DATA_ERROR, "JanusGraphDao",
+                    "Failed to create Node for ID '{}'", (Object) graphVertex.getUniqueId(), e);
                 return Either.right(JanusGraphClient.handleJanusGraphException(e));
             }
         } else {
-            logger.debug("Failed to create vertex for ID [{}]  {}", graphVertex.getUniqueId(), graph.right().value());
+            logger.debug("Failed to create vertex for ID '{}' {}", graphVertex.getUniqueId(), graph.right().value());
             return Either.right(graph.right().value());
         }
     }
@@ -330,7 +332,8 @@ public class JanusGraphDao {
             setEdgeProperties(edge, properties);
             status = JanusGraphOperationStatus.OK;
         } catch (IOException e) {
-            logger.debug("Failed to set properties on edge  properties [{}]", properties, e);
+            logger.error(EcompLoggerErrorCode.DATA_ERROR, "JanusGraphDao",
+                "Failed to set properties on edge  properties [{}]", properties, e);
             status = JanusGraphOperationStatus.GENERAL_ERROR;
         }
         return status;
index ee81931..1cf3baa 100644 (file)
  */
 package org.openecomp.sdc.be.model;
 
-import lombok.Getter;
-import lombok.Setter;
-import lombok.ToString;
-import org.onap.sdc.tosca.datatypes.model.EntrySchema;
+import lombok.NoArgsConstructor;
 import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition;
 
-@Getter
-@Setter
-@ToString
+@NoArgsConstructor
 public class AttributeDefinition extends AttributeDataDefinition implements IOperationParameter, IComplexDefaultValue {
 
-    // All names are according to TOSCA spec from
-    // https://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.3/os/TOSCA-Simple-Profile-YAML-v1.3-os.html#DEFN_ELEMENT_ATTRIBUTE_DEFN
-    private String type;
-    private String description;
-    private Object _default;
-    private String status;
-    private EntrySchema entry_schema;
-
-    public AttributeDefinition() {
-        toscaPresentation = null;
-    }
-
     public AttributeDefinition(final AttributeDataDefinition attributeDataDefinition) {
         super(attributeDataDefinition);
     }
 
-    public AttributeDefinition(final AttributeDefinition attributeDefinition) {
-        super(attributeDefinition);
-        this.type = attributeDefinition.getType();
-        this.description = attributeDefinition.getDescription();
-        this._default = attributeDefinition.get_default();
-        this.status = attributeDefinition.getStatus();
-        this.entry_schema = attributeDefinition.getEntry_schema();
-        this.toscaPresentation = attributeDefinition.toscaPresentation;
-    }
-
     @Override
     public String getDefaultValue() {
-        return _default == null ? null : String.valueOf(_default);
+        return get_default() == null ? null : String.valueOf(get_default());
     }
 
     @Override
     public void setDefaultValue(final String value) {
-        this._default = value;
+        set_default(value);
     }
 
     @Override
     public boolean isDefinition() {
         return false;
     }
+
+    @Override
+    public String toString() {
+        return "AttributeDefinition{" +
+            "name=" + getName() +
+            "uniqueId=" + getUniqueId() +
+            "ownerId=" + getOwnerId() +
+            "type=" + getType() +
+            "description=" + getDescription() +
+            "default=" + getDefaultValue() +
+            '}';
+    }
 }
index e8aba6d..10c58ba 100644 (file)
@@ -547,6 +547,11 @@ public class NodeTypeOperation extends ToscaElementOperation {
             ToscaDataDefinition.mergeDataMaps(attributesAll, attributes);
         }
         if (!attributesAll.isEmpty()) {
+            log.debug("Creating vertex for attributes {}:{}", nodeType.getName(), nodeType.getUniqueId());
+            attributesAll.forEach((s, attributeDataDefinition) -> {
+                log.debug("Attribute {}:{}", s, attributeDataDefinition.getUniqueId());
+            });
+
             Either<GraphVertex, StorageOperationStatus> assosiateElementToData = associateElementToData(nodeTypeVertex, VertexTypeEnum.ATTRIBUTES, EdgeLabelEnum.ATTRIBUTES, attributesAll);
             if (assosiateElementToData.isRight()) {
                 return assosiateElementToData.right().value();
index 32f7e14..8c8245e 100644 (file)
@@ -922,7 +922,6 @@ public abstract class ToscaElementOperation extends BaseOperation {
         switch (label) {
             case NODE_TYPE:
                 toscaElement = new NodeType();
-                toscaElement.setAttributes(getAttributesFromComponentV(componentV));
                 break;
             case TOPOLOGY_TEMPLATE:
                 toscaElement = new TopologyTemplate();
index d159da8..d90f6be 100644 (file)
  */
 package org.openecomp.sdc.be.datatypes.elements;
 
+import java.util.ArrayList;
 import java.util.List;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
+import org.apache.commons.collections.CollectionUtils;
 import org.onap.sdc.tosca.datatypes.model.EntrySchema;
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
@@ -32,7 +34,7 @@ import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
 @NoArgsConstructor
 public class AttributeDataDefinition extends ToscaDataDefinition {
 
-    private List<GetOutputValueDataDefinition> getOutputValues;
+    private transient List<GetOutputValueDataDefinition> getOutputValues;
     private String outputId;
     private String value;
     private String outputPath;
@@ -51,11 +53,15 @@ public class AttributeDataDefinition extends ToscaDataDefinition {
         this.setValue(attributeDataDefinition.getValue());
         this.setStatus(attributeDataDefinition.getStatus());
         this.setEntry_schema(attributeDataDefinition.getEntry_schema());
-        this.setSchema(attributeDataDefinition.getSchema());
         this.setOutputPath(attributeDataDefinition.getOutputPath());
         this.setInstanceUniqueId(attributeDataDefinition.getInstanceUniqueId());
         this.setAttributeId(attributeDataDefinition.getAttributeId());
         this.setParentUniqueId(attributeDataDefinition.getParentUniqueId());
+        this.setOutputId(attributeDataDefinition.getOutputId());
+        if (CollectionUtils.isNotEmpty(attributeDataDefinition.getGetOutputValues())) {
+            this.getOutputValues = new ArrayList<>(attributeDataDefinition.getGetOutputValues());
+        }
+
     }
 
     public String getUniqueId() {
@@ -89,11 +95,6 @@ public class AttributeDataDefinition extends ToscaDataDefinition {
         return (String) getToscaPresentationValue(JsonPresentationFields.TYPE);
     }
 
-    @Override
-    public void setType(final String type) {
-        setToscaPresentationValue(JsonPresentationFields.TYPE, type);
-    }
-
     public String getDescription() {
         return (String) getToscaPresentationValue(JsonPresentationFields.DESCRIPTION);
     }
@@ -119,15 +120,15 @@ public class AttributeDataDefinition extends ToscaDataDefinition {
     }
 
     public EntrySchema getEntry_schema() {
-        return (EntrySchema) getToscaPresentationValue(JsonPresentationFields.SCHEMA);
+        return (EntrySchema) getToscaPresentationValue(JsonPresentationFields.ENTRY_SCHEMA);
     }
 
     public void setEntry_schema(final EntrySchema entrySchema) {
-        setToscaPresentationValue(JsonPresentationFields.SCHEMA, entrySchema);
+        setToscaPresentationValue(JsonPresentationFields.ENTRY_SCHEMA, entrySchema);
     }
 
     public SchemaDefinition getSchema() {
-        return (SchemaDefinition) getToscaPresentationValue(JsonPresentationFields.SCHEMA);
+        return null;
     }
 
     public String getParentUniqueId() {
index 34382df..2ec5b28 100644 (file)
@@ -119,6 +119,7 @@ public enum JsonPresentationFields {
     PROPERTIES("properties", null),
     PROPERTY("property", null),
     SCHEMA("schema", null),
+    ENTRY_SCHEMA("entry_schema", null),
     VALUE("value", null),
     PARENT_UNIQUE_ID("parentUniqueId", null),
 
index 4ca4442..518e5eb 100644 (file)
@@ -23,15 +23,13 @@ package org.openecomp.sdc.be.datatypes.tosca;
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonValue;
 import fj.data.Either;
-import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
-import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
-
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.stream.Collectors;
+import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
 
 public abstract class ToscaDataDefinition {
 
@@ -138,5 +136,4 @@ public abstract class ToscaDataDefinition {
         return false;
     }
 
-    public void setSchema(final SchemaDefinition schemaDef){};
 }
index ee8c7db..7535fbd 100644 (file)
@@ -46,7 +46,7 @@ public class TypeUtils {
         DERIVED_FROM("derived_from"), IS_PASSWORD("is_password"),
         // Properties
         PROPERTIES("properties"), TYPE("type"), STATUS("status"),
-        ENTRY_SCHEMA("entry_schema"), REQUIRED("required"), DESCRIPTION("description"),
+        KEY_SCHEMA("key_schema"), ENTRY_SCHEMA("entry_schema"), REQUIRED("required"), DESCRIPTION("description"),
         DEFAULT_VALUE("default"), VALUE("value"), CONSTRAINTS("constraints"),
         DEFAULT("default"),
         // Group Types