/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2019 Nordix Foundation.
+ * Copyright (C) 2019-2020, 2022-2023 Nordix Foundation.
+ * Modifications Copyright (C) 2019-2021 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.
package org.onap.policy.models.tosca.simple.concepts;
+import jakarta.persistence.AttributeOverride;
+import jakarta.persistence.Column;
+import jakarta.persistence.ElementCollection;
+import jakarta.persistence.EmbeddedId;
+import jakarta.persistence.Lob;
+import jakarta.persistence.MappedSuperclass;
+import jakarta.ws.rs.core.Response;
+import java.io.Serial;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
-
-import javax.persistence.AttributeOverride;
-import javax.persistence.AttributeOverrides;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
-import javax.persistence.EmbeddedId;
-import javax.persistence.MappedSuperclass;
-
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
-
import org.apache.commons.lang3.ObjectUtils;
-import org.onap.policy.common.utils.validation.Assertions;
-import org.onap.policy.common.utils.validation.ParameterValidationUtils;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.PfConcept;
import org.onap.policy.models.base.PfConceptKey;
import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfModelRuntimeException;
import org.onap.policy.models.base.PfUtils;
-import org.onap.policy.models.base.PfValidationMessage;
-import org.onap.policy.models.base.PfValidationResult;
-import org.onap.policy.models.base.PfValidationResult.ValidationResult;
+import org.onap.policy.models.base.validation.annotations.VerifyKey;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntity;
/**
* Class to represent the EntrySchema of list/map property in TOSCA definition.
@MappedSuperclass
@Data
@EqualsAndHashCode(callSuper = false)
-public class JpaToscaEntityType extends PfConcept {
+public class JpaToscaEntityType<T extends ToscaEntity> extends PfConcept implements PfAuthorative<T> {
+ @Serial
private static final long serialVersionUID = -1330661834220739393L;
+ private static final StandardCoder STANDARD_CODER = new StandardCoder();
+
@EmbeddedId
+ @VerifyKey
+ @NotNull
private PfConceptKey key;
// @formatter:off
@Column
- @AttributeOverrides({
- @AttributeOverride(name = "name",
- column = @Column(name = "derived_from_name")),
- @AttributeOverride(name = "version",
- column = @Column(name = "derived_from_version"))
- })
+ @AttributeOverride(name = "name", column = @Column(name = "derived_from_name"))
+ @AttributeOverride(name = "version", column = @Column(name = "derived_from_version"))
+ @VerifyKey
private PfConceptKey derivedFrom;
@ElementCollection
- private Map<String, String> metadata;
+ @Lob
+ private Map<@NotNull @NotBlank String, @NotNull @NotBlank String> metadata;
@Column
+ @NotBlank
private String description;
+
+ private transient T toscaEntity;
// @formatter:on
/**
*
* @param copyConcept the concept to copy from
*/
- public JpaToscaEntityType(final JpaToscaEntityType copyConcept) {
+ public JpaToscaEntityType(final JpaToscaEntityType<T> copyConcept) {
super(copyConcept);
+ this.key = new PfConceptKey(copyConcept.key);
+ this.derivedFrom = (copyConcept.derivedFrom != null ? new PfConceptKey(copyConcept.derivedFrom) : null);
+ this.metadata = (copyConcept.metadata != null ? new TreeMap<>(copyConcept.metadata) : null);
+ this.description = copyConcept.description;
+ }
+
+ /**
+ * Authorative constructor.
+ *
+ * @param authorativeConcept the authorative concept to copy from
+ */
+ public JpaToscaEntityType(final T authorativeConcept) {
+ this.fromAuthorative(authorativeConcept);
}
@Override
- public List<PfKey> getKeys() {
- final List<PfKey> keyList = getKey().getKeys();
+ public T toAuthorative() {
+ toscaEntity.setName(getKey().getName());
+ toscaEntity.setVersion(getKey().getVersion());
+
if (derivedFrom != null) {
- keyList.addAll(derivedFrom.getKeys());
+ toscaEntity.setDerivedFrom(derivedFrom.getName());
}
- return keyList;
+
+ if (description != null) {
+ toscaEntity.setDescription(description);
+ }
+
+ toscaEntity.setMetadata(PfUtils.mapMap(metadata, this::deserializeMetadataValue));
+
+ return toscaEntity;
}
@Override
- public void clean() {
- key.clean();
+ public void fromAuthorative(T toscaEntity) {
+ key = new PfConceptKey();
- if (derivedFrom != null) {
- derivedFrom.clean();
+ if (toscaEntity.getName() != null) {
+ key.setName(toscaEntity.getName());
}
- if (metadata != null) {
- for (Entry<String, String> metadataEntry : metadata.entrySet()) {
- metadataEntry.setValue(metadataEntry.getValue().trim());
+ if (toscaEntity.getVersion() != null) {
+ key.setVersion(toscaEntity.getVersion());
+ }
+
+ if (toscaEntity.getDerivedFrom() != null) {
+ // Check if the derived from field contains a name-version ID
+ if (toscaEntity.getDerivedFrom().contains(":")) {
+ derivedFrom = new PfConceptKey(toscaEntity.getDerivedFrom());
+ } else {
+ derivedFrom = new PfConceptKey(toscaEntity.getDerivedFrom(), PfKey.NULL_KEY_VERSION);
}
}
- description = (description != null ? description.trim() : null);
+ if (toscaEntity.getDescription() != null) {
+ description = toscaEntity.getDescription();
+ }
+
+ metadata = PfUtils.mapMap(toscaEntity.getMetadata(), this::serializeMetadataValue);
}
@Override
- public PfValidationResult validate(PfValidationResult resultIn) {
- PfValidationResult result = resultIn;
-
- if (key.isNullKey()) {
- result.addValidationMessage(
- new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
+ public List<PfKey> getKeys() {
+ final List<PfKey> keyList = getKey().getKeys();
+ if (derivedFrom != null) {
+ keyList.addAll(derivedFrom.getKeys());
}
+ return keyList;
+ }
- result = key.validate(result);
+ @Override
+ public void clean() {
+ key.clean();
- if (derivedFrom != null && derivedFrom.isNullKey()) {
- result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
- "derived from key is a null key"));
+ if (derivedFrom != null) {
+ derivedFrom.clean();
}
if (metadata != null) {
for (Entry<String, String> metadataEntry : metadata.entrySet()) {
- if (!ParameterValidationUtils.validateStringParameter(metadataEntry.getKey())) {
- result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
- "property metadata key may not be null"));
- }
- if (!ParameterValidationUtils.validateStringParameter(metadataEntry.getValue())) {
- result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
- "property metadata value may not be null"));
- }
+ metadataEntry.setValue(metadataEntry.getValue().trim());
}
}
- if (description != null && description.trim().length() == 0) {
- result.addValidationMessage(new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID,
- "property description may not be blank"));
- }
-
- return result;
+ description = (description != null ? description.trim() : null);
}
@Override
return 0;
}
if (getClass() != otherConcept.getClass()) {
- return this.hashCode() - otherConcept.hashCode();
+ return getClass().getName().compareTo(otherConcept.getClass().getName());
}
- final JpaToscaEntityType other = (JpaToscaEntityType) otherConcept;
- if (!key.equals(other.key)) {
- return key.compareTo(other.key);
+ @SuppressWarnings("unchecked")
+ final JpaToscaEntityType<T> other = (JpaToscaEntityType<T>) otherConcept;
+
+ int result = key.compareTo(other.key);
+ if (result != 0) {
+ return result;
}
- int result = ObjectUtils.compare(derivedFrom, other.derivedFrom);
+ result = ObjectUtils.compare(derivedFrom, other.derivedFrom);
if (result != 0) {
return result;
}
- result = PfUtils.compareObjects(metadata, other.metadata);
+ result = PfUtils.compareMaps(metadata, other.metadata);
if (result != 0) {
return result;
}
return ObjectUtils.compare(description, other.description);
}
- @Override
- public PfConcept copyTo(@NonNull PfConcept target) {
- final Object copyObject = target;
- Assertions.instanceOf(copyObject, PfConcept.class);
-
- final JpaToscaEntityType copy = ((JpaToscaEntityType) copyObject);
- copy.setKey(new PfConceptKey(key));
- copy.setDerivedFrom(derivedFrom != null ? new PfConceptKey(derivedFrom) : null);
-
- if (metadata != null) {
- final Map<String, String> newMatadata = new TreeMap<>();
- for (final Entry<String, String> metadataEntry : metadata.entrySet()) {
- newMatadata.put(metadataEntry.getKey(), metadataEntry.getValue());
- }
- copy.setMetadata(newMatadata);
+ protected Object deserializeMetadataValue(String metadataValue) {
+ try {
+ return STANDARD_CODER.decode(metadataValue, Object.class);
+ } catch (CoderException ce) {
+ String errorMessage = "error decoding metadata JSON value read from database: " + metadataValue;
+ throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, errorMessage, ce);
}
+ }
- copy.setDescription(description);
-
- return copy;
+ protected String serializeMetadataValue(Object metadataValue) {
+ try {
+ return STANDARD_CODER.encode(metadataValue);
+ } catch (CoderException ce) {
+ String errorMessage = "error encoding metadata JSON value for database: " + metadataValue;
+ throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, errorMessage, ce);
+ }
}
}