aboutsummaryrefslogtreecommitdiffstats
path: root/jtosca/src/main/java/org/onap/sdc/toscaparser/api/Property.java
diff options
context:
space:
mode:
Diffstat (limited to 'jtosca/src/main/java/org/onap/sdc/toscaparser/api/Property.java')
-rw-r--r--jtosca/src/main/java/org/onap/sdc/toscaparser/api/Property.java401
1 files changed, 401 insertions, 0 deletions
diff --git a/jtosca/src/main/java/org/onap/sdc/toscaparser/api/Property.java b/jtosca/src/main/java/org/onap/sdc/toscaparser/api/Property.java
new file mode 100644
index 0000000..e20bd2f
--- /dev/null
+++ b/jtosca/src/main/java/org/onap/sdc/toscaparser/api/Property.java
@@ -0,0 +1,401 @@
+/*-
+ * ============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.onap.sdc.toscaparser.api;
+
+import com.google.common.collect.Lists;
+import org.onap.sdc.toscaparser.api.elements.constraints.Constraint;
+import org.onap.sdc.toscaparser.api.elements.constraints.Schema;
+import org.onap.sdc.toscaparser.api.functions.Function;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class Property {
+ // TOSCA built-in Property type
+ private static final Logger LOGGER = LoggerFactory.getLogger(Property.class.getName());
+
+ private static final String TYPE = "type";
+ private static final String REQUIRED = "required";
+ private static final String DESCRIPTION = "description";
+ private static final String DEFAULT = "default";
+ private static final String CONSTRAINTS = "constraints";
+ private static String entrySchema = "entry_schema";
+ private static String dataType = "datatypes";
+
+ private static final String[] PROPERTY_KEYS = {
+ TYPE, REQUIRED, DESCRIPTION, DEFAULT, CONSTRAINTS};
+
+ private static final String ENTRYTYPE = "type";
+ private static final String ENTRYPROPERTIES = "properties";
+ private static final String PATH_DELIMITER = "#";
+ private static final String[] ENTRY_SCHEMA_KEYS = {
+ ENTRYTYPE, ENTRYPROPERTIES};
+
+ private String name;
+ private Object value;
+ private Schema schema;
+ private LinkedHashMap<String, Object> customDef;
+
+ public Property(Map.Entry<String, Object> propertyEntry) {
+ name = propertyEntry.getKey();
+ value = propertyEntry.getValue();
+ }
+
+ public Property(String propname,
+ Object propvalue,
+ LinkedHashMap<String, Object> propschemaDict,
+ LinkedHashMap<String, Object> propcustomDef) {
+
+ name = propname;
+ value = propvalue;
+ customDef = propcustomDef;
+ schema = new Schema(propname, propschemaDict);
+ }
+
+ public String getType() {
+ return schema.getType();
+ }
+
+ public boolean isRequired() {
+ return schema.isRequired();
+ }
+
+ public String getDescription() {
+ return schema.getDescription();
+ }
+
+ public Object getDefault() {
+ return schema.getDefault();
+ }
+
+ public ArrayList<Constraint> getConstraints() {
+ return schema.getConstraints();
+ }
+
+ public LinkedHashMap<String, Object> getEntrySchema() {
+ return schema.getEntrySchema();
+ }
+
+
+ public String getName() {
+ return name;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ // setter
+ public Object setValue(Object vob) {
+ value = vob;
+ return value;
+ }
+
+ public void validate() {
+ // Validate if not a reference property
+ if (!Function.isFunction(value)) {
+ if (getType().equals(Schema.STRING)) {
+ value = value.toString();
+ }
+ value = DataEntity.validateDatatype(getType(), value,
+ getEntrySchema(),
+ customDef,
+ name);
+ validateConstraints();
+ }
+ }
+
+ private void validateConstraints() {
+ if (getConstraints() != null) {
+ for (Constraint constraint : getConstraints()) {
+ constraint.validate(value);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Property{"
+ + "name='" + name + '\''
+ + ", value=" + value
+ + ", schema=" + schema
+ + ", customDef=" + customDef
+ + '}';
+ }
+
+ /**
+ * Retrieves property value as list of strings if<br>
+ * - the value is simple<br>
+ * - the value is list of simple values<br>
+ * - the provided path refers to a simple property inside a data type<br>
+ *
+ * @param propertyPath valid name of property for search.<br>
+ * If a name refers to a simple field inside a datatype, the property name should be defined with # delimiter.<br>
+ * @return List of property values. If not found, empty list will be returned.<br>
+ * If property value is a list either of simple fields or of simple fields inside a datatype, all values from the list should be returned
+ */
+ public List<String> getLeafPropertyValue(String propertyPath) {
+ List<String> propertyValueList = Collections.emptyList();
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("getLeafPropertyValue=> A new request: propertyPath: {}, value: {}", propertyPath, getValue());
+ }
+ if (propertyPath == null || getValue() == null
+ //if entry_schema disappears, it is datatype,
+ // otherwise it is map of simple types - should be ignored
+ || isValueMapOfSimpleTypes()) {
+ LOGGER.error("It is a wrong request - ignoring! propertyPath: {}, value: {}", propertyPath, getValue());
+ return propertyValueList;
+ }
+ String[] path = propertyPath.split(PATH_DELIMITER);
+
+ if (Schema.isRequestedTypeSimple(getPropertyTypeByPath(path))) {
+ //the internal property type in the path is either simple or list of simple types
+ if (isValueInsideDataType()) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("The requested is an internal simple property inside of a data type");
+ }
+ //requested value is an internal simple property inside of a data type
+ propertyValueList = getSimplePropertyValueForComplexType(path);
+ } else {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("The requested property has simple type or list of simple types");
+ }
+ //the requested property is simple type or list of simple types
+ propertyValueList = getSimplePropertyValueForSimpleType();
+ }
+ }
+ return propertyValueList;
+ }
+
+ private boolean isValueMapOfSimpleTypes() {
+ if (getValue() instanceof Map && getEntrySchema() != null) {
+ LOGGER.warn("This property value is a map of simple types");
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isValueInsideDataType() {
+ //value is either a list of values for data type
+ //or data type
+ return (Schema.LIST.equals(getType()) && isDataTypeInEntrySchema())
+ || (getEntrySchema() == null && getType().contains(dataType));
+ }
+
+ private Object getSimpleValueFromComplexObject(Object current, String[] path) {
+ if (current == null) {
+ return null;
+ }
+ int index = 0;
+
+ if (path.length > index) {
+ for (int i = index; i < path.length; i++) {
+ if (current instanceof Map) {
+ current = ((Map<String, Object>) current).get(path[i]);
+ } else if (current instanceof List) {
+ current = ((List) current).get(0);
+ i--;
+ } else {
+ return null;
+ }
+ }
+ }
+ if (current != null) {
+ return current;
+ }
+ return null;
+ }
+
+ private List<String> getSimplePropertyValueForSimpleType() {
+ if (getValue() instanceof List || getValue() instanceof Map) {
+ return getSimplePropertyValueForComplexType(null);
+ }
+ return Lists.newArrayList(String.valueOf(value));
+ }
+
+ private List<String> getSimplePropertyValueForComplexType(String[] path) {
+ if (getValue() instanceof List) {
+ return ((List<Object>) getValue()).stream()
+ .map(v -> {
+ if (path != null) {
+ return getSimpleValueFromComplexObject(v, path);
+ } else {
+ return v;
+ }
+ })
+ //it might be null when get_input can't be resolved
+ // e.g.:
+ // - get_input has two parameters: 1. list and 2. index in this list
+ //and list has no value
+ // - neither value no default is defined for get_input
+ .filter(Objects::nonNull)
+ .map(String::valueOf)
+ .collect(Collectors.toList());
+ }
+ //it is data type
+ List<String> valueList = Lists.newArrayList();
+ String valueString = String.valueOf(getSimpleValueFromComplexObject(getValue(), path));
+ if (Objects.nonNull(valueString)) {
+ valueList.add(valueString);
+ }
+ return valueList;
+ }
+
+ private String getPropertyTypeByPath(String[] path) {
+ String propertyType = calculatePropertyType();
+
+ if (path.length > 0 && !path[0].isEmpty()) {
+ return getInternalPropertyType(propertyType, path, 0);
+ }
+ return propertyType;
+ }
+
+ private String calculatePropertyType() {
+ String propertyType = getType();
+ if (Schema.LIST.equals(propertyType)) {
+ //if it is list, return entry schema type
+ return (String) getEntrySchema().get(ENTRYTYPE);
+ }
+ return propertyType;
+ }
+
+ private String calculatePropertyType(LinkedHashMap<String, Object> property) {
+ String type = (String) property.get(TYPE);
+ if (Schema.LIST.equals(type)) {
+ //it might be a data type
+ return getEntrySchemaType(property);
+ }
+ return type;
+ }
+
+ private String getInternalPropertyType(String dataTypeName, String[] path, int index) {
+ if (path.length > index) {
+ LinkedHashMap<String, Object> complexProperty = (LinkedHashMap<String, Object>) customDef.get(dataTypeName);
+ if (complexProperty != null) {
+ LinkedHashMap<String, Object> dataTypeProperties = (LinkedHashMap<String, Object>) complexProperty.get(ENTRYPROPERTIES);
+ return getPropertyTypeFromCustomDefDeeply(path, index, dataTypeProperties);
+ }
+ }
+ //stop searching - seems as wrong flow: the path is finished but the value is not found yet
+ return null;
+ }
+
+ private String getEntrySchemaType(LinkedHashMap<String, Object> property) {
+ LinkedHashMap<String, Object> entrySchema = (LinkedHashMap<String, Object>) property.get(Property.entrySchema);
+ if (entrySchema != null) {
+ return (String) entrySchema.get(TYPE);
+ }
+ return null;
+ }
+
+ private String getPropertyTypeFromCustomDefDeeply(String[] path, int index, LinkedHashMap<String, Object> properties) {
+ if (properties != null) {
+ LinkedHashMap<String, Object> foundProperty = (LinkedHashMap<String, Object>) (properties).get(path[index]);
+ if (foundProperty != null) {
+ String propertyType = calculatePropertyType(foundProperty);
+ if (propertyType == null || index == path.length - 1) {
+ return propertyType;
+ }
+ return getInternalPropertyType(propertyType, path, index + 1);
+ }
+ }
+ return null;
+ }
+
+ private boolean isDataTypeInEntrySchema() {
+ String entrySchemaType = (String) getEntrySchema().get(ENTRYTYPE);
+ return entrySchemaType != null && entrySchemaType.contains(dataType);
+ }
+
+
+}
+
+/*python
+
+class Property(object):
+ '''TOSCA built-in Property type.'''
+
+ PROPERTY_KEYS = (
+ TYPE, REQUIRED, DESCRIPTION, DEFAULT, CONSTRAINTS
+ ) = (
+ 'type', 'required', 'description', 'default', 'constraints'
+ )
+
+ ENTRY_SCHEMA_KEYS = (
+ ENTRYTYPE, ENTRYPROPERTIES
+ ) = (
+ 'type', 'properties'
+ )
+
+ def __init__(self, property_name, value, schema_dict, custom_def=None):
+ self.name = property_name
+ self.value = value
+ self.custom_def = custom_def
+ self.schema = Schema(property_name, schema_dict)
+
+ @property
+ def type(self):
+ return self.schema.type
+
+ @property
+ def required(self):
+ return self.schema.required
+
+ @property
+ def description(self):
+ return self.schema.description
+
+ @property
+ def default(self):
+ return self.schema.default
+
+ @property
+ def constraints(self):
+ return self.schema.constraints
+
+ @property
+ def entry_schema(self):
+ return self.schema.entry_schema
+
+ def validate(self):
+ '''Validate if not a reference property.'''
+ if not is_function(self.value):
+ if self.type == Schema.STRING:
+ self.value = str(self.value)
+ self.value = DataEntity.validate_datatype(self.type, self.value,
+ self.entry_schema,
+ self.custom_def,
+ self.name)
+ self._validate_constraints()
+
+ def _validate_constraints(self):
+ if self.constraints:
+ for constraint in self.constraints:
+ constraint.validate(self.value)
+*/