diff options
author | Phillip Leigh <Phillip.Leigh@amdocs.com> | 2019-10-28 15:55:40 -0400 |
---|---|---|
committer | Phillip Leigh <Phillip.Leigh@amdocs.com> | 2019-10-29 17:36:53 -0400 |
commit | 2e2f969676ab391fba2198cbaa55e9b85d50216f (patch) | |
tree | e0bee9dbd3a7933d44173be99e0efe7df5b7b412 /aai-schema-abstraction/src/main | |
parent | 0a10810750640260a3d0476afc17575d7700ed0d (diff) |
[AAI-2404]add aai-schema-abstraction library
Signed-off-by: Phillip Leigh <Phillip.Leigh@amdocs.com>
Issue-ID: AAI-2404
Change-Id: I30d954bcdf1cf020191028160610defb8dbc8ff6
Diffstat (limited to 'aai-schema-abstraction/src/main')
37 files changed, 3730 insertions, 0 deletions
diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/SchemaProvider.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/SchemaProvider.java new file mode 100644 index 00000000..1e798196 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/SchemaProvider.java @@ -0,0 +1,97 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.onap.aai.schemaif.definitions.EdgeSchema; +import org.onap.aai.schemaif.definitions.VertexSchema; + +public interface SchemaProvider { + + /** + * Load the schema into memory + */ + public void loadSchema() throws SchemaProviderException; + + /** + * Get the identifier for the more recent version of the schema + * + * @return The schema version identifier + */ + public String getLatestSchemaVersion() throws SchemaProviderException; + + /** + * Get the schema definition for a vertex + * + * @param vertexName - Name of the vertex + * @param schemaVersion - Version of the schema to use + * + * @return The vertex schema definition + */ + public VertexSchema getVertexSchema(String vertexName, String schemaVersion) throws SchemaProviderException; + + /** + * Get the schema definition for an edge + * + * @param edgeType - Type of the edge + * @param sourceVertex - The source vertex for the edge + * @param targetVertex - The target vertex for the edge + * @param schemaVersion - Version of the schema to use + * + * @return The edge schema definition + */ + public EdgeSchema getEdgeSchema(String edgeType, String sourceVertex, String targetVertex, String version) throws SchemaProviderException; + + /** + * Get the list of edge definitions which are adjacent to the given vertex + * + * @param vertexType - Type of the vertex + * @param schemaVersion - Version of the schema to use + * + * @return The list of edge schema definitions + */ + public Set<EdgeSchema> getAdjacentEdgeSchema(String vertexType, String version) throws SchemaProviderException; + + /** + * Get the list of edge definitions which are valid for the given source and target + * + * @param sourceType - Type of the source vertex + * @param targetType - Type of the target vertex + * @param schemaVersion - Version of the schema to use + * + * @return The list of edge schema definitions + */ + public Set<EdgeSchema> getEdgeSchemaForSourceTarget(String sourceType, String targetType, String version) throws SchemaProviderException; + + /** + * Get vertex map for a schema version + * + * @param schemaVersion - Version of the schema to use + * + * @return The list of vertex types + */ + public Map<String, VertexSchema> getVertexMap(String schemaVersion) throws SchemaProviderException; + + } diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/SchemaProviderException.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/SchemaProviderException.java new file mode 100644 index 00000000..9a95c337 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/SchemaProviderException.java @@ -0,0 +1,47 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif; + + +public class SchemaProviderException extends Exception { + + private static final long serialVersionUID = 8162385108397238865L; + + + public SchemaProviderException() {} + + public SchemaProviderException(String message) { + super(message); + } + + public SchemaProviderException(Throwable cause) { + super(cause); + } + + public SchemaProviderException(String message, Throwable cause) { + super(message, cause); + } + + public SchemaProviderException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/SchemaProviderMsgs.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/SchemaProviderMsgs.java new file mode 100644 index 00000000..9b2c1518 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/SchemaProviderMsgs.java @@ -0,0 +1,37 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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========================================================= + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +package org.onap.aai.schemaif; + +import com.att.eelf.i18n.EELFResourceManager; +import org.onap.aai.cl.eelf.LogMessageEnum; + +public enum SchemaProviderMsgs implements LogMessageEnum { + SCHEMA_LOAD_ERROR, + LOADED_SCHEMA_FILE, + LOADED_DB_RULE_FILE; + + static { + EELFResourceManager.loadMessageBundle("logging/SchemaProviderMsgs"); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/EdgeSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/EdgeSchema.java new file mode 100644 index 00000000..07dd65d1 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/EdgeSchema.java @@ -0,0 +1,116 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions; + +import java.util.Map; + + +public class EdgeSchema { + protected String name; + protected String source; + protected String target; + protected Multiplicity multiplicity; + protected Map<String,String> annotations; + protected Map<String,PropertySchema> properties; + + public enum Multiplicity { + MANY_2_MANY, + MANY_2_ONE, + ONE_2_MANY, + ONE_2_ONE + } + + public String getName() { + return name; + } + + public String getSource() { + return source; + } + + public String getTarget() { + return target; + } + + public Multiplicity getMultiplicity() { + return multiplicity; + } + + public PropertySchema getPropertySchema(String propName) { + return properties.get(propName.toLowerCase()); + } + + public Map<String,PropertySchema> getPropertySchemaList() { + return properties; + } + + public String getAnnotationValue(String annotation) { + return annotations.get(annotation.toLowerCase()); + } + + public Map<String,String> getAnnotations() { + return annotations; + } + + @Override + public int hashCode() { + String key = source + target + name; + return key.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (getClass() != obj.getClass()) { + return false; + } + + EdgeSchema other = (EdgeSchema) obj; + + if ( (!source.equals(other.getSource())) || (!target.equals(other.getTarget())) || (!name.equals(other.getName())) ) { + return false; + } + + return true; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("edge: " + getSource() + " -> " + getTarget() + "\n"); + sb.append(" type: " + getName() + "\n"); + sb.append(" multiplicity: " + getMultiplicity() + "\n"); + + sb.append(" annotations: " + "\n"); + for (String annotation : annotations.keySet()) { + sb.append(" " + annotation + ": " + annotations.get(annotation) + "\n"); + } + sb.append(" properties: " + "\n"); + for (PropertySchema attrSchema : getPropertySchemaList().values()) { + sb.append(attrSchema.toString()); + } + + return sb.toString(); + } + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/PropertySchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/PropertySchema.java new file mode 100644 index 00000000..a512da0b --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/PropertySchema.java @@ -0,0 +1,100 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions; + +import java.util.Map; + +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.definitions.types.DataType; + + +public class PropertySchema { + protected String name; + protected DataType dataType; + protected Boolean required; + protected String defaultValue; + protected Boolean unique; + protected Boolean isReserved; + protected Map<String,String> annotations; + + public String getName() { + return name; + } + + public DataType getDataType() { + return dataType; + } + + public Boolean isRequired() { + return required; + } + + public Boolean isKey() { + return (unique && required); + } + + public Boolean isUnique() { + return unique; + } + + public String getDefaultValue() { + return defaultValue; + } + + public Boolean isReserved() { + return isReserved; + } + + public String getAnnotationValue(String annotation) { + return annotations.get(annotation.toLowerCase()); + } + + public Map<String, String> getAnnotations() { + return annotations; + } + + public Object validateValue(String value) throws SchemaProviderException { + Object obj = dataType.validateValue(value); + if (obj == null) { + throw new SchemaProviderException("Invalid value for porperty '" + name + "': " + value); + } + + return obj; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(" property: " + getName() + "\n"); + sb.append(" datatype: " + dataType.toString() + "\n"); + sb.append(" required: " + isRequired() + "\n"); + sb.append(" key: " + isKey() + "\n"); + sb.append(" reserved: " + isReserved() + "\n"); + sb.append(" default: " + getDefaultValue() + "\n"); + sb.append(" annotations: " + "\n"); + + for (String annotation : annotations.keySet()) { + sb.append(" " + annotation + ": " + annotations.get(annotation) + "\n"); + } + + return sb.toString(); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/VertexSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/VertexSchema.java new file mode 100644 index 00000000..7ad1cfc6 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/VertexSchema.java @@ -0,0 +1,65 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions; + +import java.util.Map; + + +public class VertexSchema { + protected String name; + protected Map<String,PropertySchema> properties; + protected Map<String,String> annotations; + + public String getName() { + return name; + } + + public PropertySchema getPropertySchema(String propName) { + return properties.get(propName.toLowerCase()); + } + + public Map<String,PropertySchema> getPropertySchemaList() { + return properties; + } + + public Map<String,String> getAnnotationSchemaList() { + return annotations; + } + + public String getAnnotationValue(String annotation) { + return annotations.get(annotation.toLowerCase()); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("vertex: " + getName() + "\n"); + sb.append(" annotations: " + "\n"); + for (String annotation : annotations.keySet()) { + sb.append(" " + annotation + ": " + annotations.get(annotation) + "\n"); + } + sb.append(" properties: " + "\n"); + for (PropertySchema attrSchema : getPropertySchemaList().values()) { + sb.append(attrSchema.toString()); + } + + return sb.toString(); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/BooleanDataType.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/BooleanDataType.java new file mode 100644 index 00000000..52fb4ca5 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/BooleanDataType.java @@ -0,0 +1,38 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions.types; + + +public class BooleanDataType extends DataType { + public BooleanDataType() { + super(Type.BOOL); + } + + @Override + public Object validateValue(String value) { + if (value.equalsIgnoreCase("true") || (value.equalsIgnoreCase("false"))) { + return Boolean.parseBoolean(value); + } + + return null; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/ComplexDataType.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/ComplexDataType.java new file mode 100644 index 00000000..e09c18fd --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/ComplexDataType.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions.types; + +import java.util.List; + +import org.onap.aai.schemaif.definitions.PropertySchema; + +public class ComplexDataType extends DataType { + private List<PropertySchema> subProperties; + + public ComplexDataType(List<PropertySchema> subProperties) { + super(Type.COMPLEX); + this.subProperties = subProperties; + } + + public List<PropertySchema> getSubProperties() { + return subProperties; + } + + @Override + public Object validateValue(String value) { + // TODO: Validate the complex type against the subProperties + return value; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("COMPLEX[ "); + + for (PropertySchema prop : getSubProperties()) { + sb.append(prop.getDataType().toString() + " "); + } + + sb.append("]"); + + return sb.toString(); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/DataType.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/DataType.java new file mode 100644 index 00000000..a0586037 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/DataType.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions.types; + +import org.onap.aai.schemaif.SchemaProviderException; + +public abstract class DataType { + public enum Type { + STRING, + BOOL, + INT, + LONG, + FLOAT, + LIST, + MAP, + COMPLEX + } + + private Type type; + + public DataType(Type type) { + this.type = type; + } + + public Type getType() { + return type; + } + + public abstract Object validateValue(String value); + + public String toString() { + return getType().toString(); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/FloatDataType.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/FloatDataType.java new file mode 100644 index 00000000..17fb9485 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/FloatDataType.java @@ -0,0 +1,43 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions.types; + +public class FloatDataType extends DataType { + public FloatDataType() { + super(Type.FLOAT); + } + + @Override + public Object validateValue(String value) { + // TODO: In Tosca, you can impose constraints such as min/max value. + // In future we can add this type of validation + Float floatValue; + try { + floatValue = Float.parseFloat(value); + } + catch (NumberFormatException e) { + return null; + } + + return floatValue; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/IntDataType.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/IntDataType.java new file mode 100644 index 00000000..59eb788f --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/IntDataType.java @@ -0,0 +1,54 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions.types; + +import java.text.DecimalFormat; + +public class IntDataType extends DataType { + public IntDataType() { + super(Type.INT); + } + + @Override + public Object validateValue(String value) { + // TODO: In Tosca, you can impose constraints such as min/max value. + // In future we can add this type of validation + Integer intValue; + try { + intValue = Integer.parseInt(value); + } + catch (NumberFormatException e) { + // There is an edge case where an int value is stored as "x.0" in champ. + // In that case, we just want to drop the ".0" and treat it as a proper + // integer + try { + DecimalFormat decimalFormat = new DecimalFormat("0.#"); + intValue = Integer.parseInt(decimalFormat.format(Double.valueOf(value))); + } + catch (Exception ex) { + return null; + } + } + + return intValue; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/ListDataType.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/ListDataType.java new file mode 100644 index 00000000..84adefec --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/ListDataType.java @@ -0,0 +1,45 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions.types; + +public class ListDataType extends DataType { + private DataType listType; + + public ListDataType(DataType listType) { + super(Type.LIST); + this.listType = listType; + } + + public DataType getListType() { + return listType; + } + + @Override + public Object validateValue(String value) { + // TODO: Break the string into a list and validate each element against the listType + return value; + } + + public String toString() { + return "LIST[" + listType.toString() + "]"; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/LongDataType.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/LongDataType.java new file mode 100644 index 00000000..38195f9c --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/LongDataType.java @@ -0,0 +1,43 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions.types; + +public class LongDataType extends DataType { + public LongDataType() { + super(Type.LONG); + } + + @Override + public Object validateValue(String value) { + // TODO: In Tosca, you can impose constraints such as min/max value. + // In future we can add this type of validation + Long longInt; + try { + longInt = Long.parseLong(value); + } + catch (NumberFormatException e) { + return null; + } + + return longInt; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/MapDataType.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/MapDataType.java new file mode 100644 index 00000000..443f460e --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/MapDataType.java @@ -0,0 +1,45 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions.types; + +public class MapDataType extends DataType { + private DataType mapType; + + public MapDataType(DataType mapType) { + super(Type.MAP); + this.mapType = mapType; + } + + public DataType getMapType() { + return mapType; + } + + @Override + public Object validateValue(String value) { + // TODO: Break the string into a map and validate each element against the mapType + return value; + } + + public String toString() { + return "MAP[" + mapType.toString() + "]"; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/StringDataType.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/StringDataType.java new file mode 100644 index 00000000..39487ea2 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/definitions/types/StringDataType.java @@ -0,0 +1,35 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.definitions.types; + +public class StringDataType extends DataType { + public StringDataType() { + super(Type.STRING); + } + + @Override + public Object validateValue(String value) { + // TODO: In Tosca, you can impose constraints such as string length, regex matches, valid values, + // string length maximums, etc. In future we can add this type of validation + return value; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/FromJsonEdgeSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/FromJsonEdgeSchema.java new file mode 100644 index 00000000..e3bc450b --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/FromJsonEdgeSchema.java @@ -0,0 +1,82 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json; + +import java.util.HashMap; +import java.util.Map; + +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.definitions.EdgeSchema; +import org.onap.aai.schemaif.definitions.PropertySchema; +import org.onap.aai.schemaif.json.definitions.JsonEdgeSchema; + +public class FromJsonEdgeSchema extends EdgeSchema { + public static final String WILDCARD_CHAR = "*"; + + public FromJsonEdgeSchema() { + } + + public FromJsonEdgeSchema(EdgeSchema other) { + // A shallow copy should suffice, as edge definitions don't change. + name = other.getName(); + source = other.getSource(); + target = other.getTarget(); + multiplicity = other.getMultiplicity(); + properties = other.getPropertySchemaList(); + annotations = other.getAnnotations(); + } + + public void fromJson(JsonEdgeSchema jsonEdge) throws SchemaProviderException { + + name = jsonEdge.getLabel(); + source = jsonEdge.getFrom(); + target = jsonEdge.getTo(); + + // TODO: At present, multiplicity isn't described in the JSON schema. By default, make everything + // many-to-many + multiplicity = Multiplicity.MANY_2_MANY; + + // Populate annotation schema + annotations = new HashMap<String,String>(); + if (jsonEdge.getAnnotations() != null) { + for (Map.Entry<String,String> entry : jsonEdge.getAnnotations().entrySet()) { + annotations.put(entry.getKey().toLowerCase(), entry.getValue()); + } + } + + // Currently edge properties are not supported in the json schema + properties = new HashMap<String,PropertySchema>(); + } + + public void replaceWildcard(String vertexName) throws SchemaProviderException { + if (source.equals(WILDCARD_CHAR) && target.equals(WILDCARD_CHAR)) { + throw new SchemaProviderException("Edge definition with wildcard source and target: " + toString()); + } + + if (source.equals(WILDCARD_CHAR)) { + source = vertexName; + } + + if (target.equals(WILDCARD_CHAR)) { + target = vertexName; + } + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/FromJsonPropertySchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/FromJsonPropertySchema.java new file mode 100644 index 00000000..ea522191 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/FromJsonPropertySchema.java @@ -0,0 +1,116 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.definitions.PropertySchema; +import org.onap.aai.schemaif.definitions.types.BooleanDataType; +import org.onap.aai.schemaif.definitions.types.ComplexDataType; +import org.onap.aai.schemaif.definitions.types.DataType; +import org.onap.aai.schemaif.definitions.types.IntDataType; +import org.onap.aai.schemaif.definitions.types.ListDataType; +import org.onap.aai.schemaif.definitions.types.LongDataType; +import org.onap.aai.schemaif.definitions.types.MapDataType; +import org.onap.aai.schemaif.definitions.types.StringDataType; +import org.onap.aai.schemaif.json.definitions.DataTypeDefinition; +import org.onap.aai.schemaif.json.definitions.JsonPropertySchema; + +public class FromJsonPropertySchema extends PropertySchema { + + public void fromJson(JsonPropertySchema pSchema, boolean reserved, List<DataTypeDefinition> dataTypes) throws SchemaProviderException { + name = pSchema.getName(); + defaultValue = pSchema.getDefaultValue() == null ? "" : pSchema.getDefaultValue(); + required = pSchema.getRequired() == null ? false : pSchema.getRequired(); + unique = pSchema.getUnique() == null ? false : pSchema.getUnique(); + isReserved = reserved; + dataType = resolveDataType(pSchema.getDataType(), dataTypes); + + // Populate annotations + annotations = new HashMap<String,String>(); + if (pSchema.getAnnotations() != null) { + for (Map.Entry<String,String> entry : pSchema.getAnnotations().entrySet()) { + annotations.put(entry.getKey().toLowerCase(), entry.getValue()); + } + } + } + + private DataType resolveDataType(String typeString, List<DataTypeDefinition> dataTypes) throws SchemaProviderException { + if (typeString.equalsIgnoreCase("string")) { + return new StringDataType(); + } + + if (typeString.equalsIgnoreCase("integer")) { + return new IntDataType(); + } + + if (typeString.equalsIgnoreCase("long")) { + return new LongDataType(); + } + + if (typeString.equalsIgnoreCase("boolean")) { + return new BooleanDataType(); + } + + if (typeString.startsWith("list:")) { + String segments[] = typeString.split(":"); + DataType subType = resolveDataType(segments[1], dataTypes); + return new ListDataType(subType); + } + + if (typeString.startsWith("map:")) { + String segments[] = typeString.split(":"); + DataType subType = resolveDataType(segments[1], dataTypes); + return new MapDataType(subType); + } + + // Must be a complex type + return resolveComplexDataType(typeString, dataTypes); + } + + private DataType resolveComplexDataType(String typeString, List<DataTypeDefinition> dataTypes) throws SchemaProviderException { + // It must be a custom/complex type. + DataTypeDefinition dType = null; + for (DataTypeDefinition d : dataTypes) { + if ( (d.getName().equals(typeString)) ) { + dType = d; + break; + } + } + + if (dType == null) { + throw new SchemaProviderException("Invalid data type: " + typeString); + } + + List<PropertySchema> propList = new ArrayList<PropertySchema>(); + for (JsonPropertySchema p : dType.getProperties()) { + FromJsonPropertySchema pSchema = new FromJsonPropertySchema(); + pSchema.fromJson(p, false, dataTypes); + propList.add(pSchema); + } + + return new ComplexDataType(propList); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/FromJsonVertexSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/FromJsonVertexSchema.java new file mode 100644 index 00000000..7a3251f1 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/FromJsonVertexSchema.java @@ -0,0 +1,132 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.definitions.PropertySchema; +import org.onap.aai.schemaif.definitions.VertexSchema; +import org.onap.aai.schemaif.json.definitions.DataTypeDefinition; +import org.onap.aai.schemaif.json.definitions.JsonPropertySchema; +import org.onap.aai.schemaif.json.definitions.JsonVertexSchema; + + +public class FromJsonVertexSchema extends VertexSchema { + public void fromJson(JsonVertexSchema jsonVertex, List<DataTypeDefinition> dataTypes, List<JsonPropertySchema> commonProps) throws SchemaProviderException { + name = jsonVertex.getName(); + properties = new HashMap<String,PropertySchema>(); + annotations = new HashMap<String,String>(); + + // Populate property schema + if (jsonVertex.getProperties() != null) { + for (JsonPropertySchema pSchema : jsonVertex.getProperties()) { + FromJsonPropertySchema propSchema = new FromJsonPropertySchema(); + propSchema.fromJson(pSchema, false, dataTypes); + properties.put(propSchema.getName().toLowerCase(), propSchema); + } + } + + // Add common properties + if (commonProps != null) { + for (JsonPropertySchema pSchema : commonProps) { + FromJsonPropertySchema propSchema = new FromJsonPropertySchema(); + propSchema.fromJson(pSchema, true, dataTypes); + properties.put(propSchema.getName().toLowerCase(), propSchema); + } + } + else { + // TODO: This is a hack until the schema-service return the list of common props + addCommonProps(); + } + + // Populate annotation schema + if (jsonVertex.getAnnotations() != null) { + for (Map.Entry<String,String> entry : jsonVertex.getAnnotations().entrySet()) { + annotations.put(entry.getKey().toLowerCase(), entry.getValue()); + } + } + + // The searchable and indexed annotations, need to grab these from the property annotations + // and store them at the vertex level as well (backwards compatibility with OXM) + StringBuilder searchableVal = new StringBuilder(); + StringBuilder indexedVal = new StringBuilder(); + for (PropertySchema pSchema : properties.values()) { + if ( (pSchema.getAnnotationValue("searchable") != null) + && (pSchema.getAnnotationValue("searchable").equalsIgnoreCase("true")) ) { + if (searchableVal.length() > 0) { + searchableVal.append(","); + } + searchableVal.append(pSchema.getName()); + } + if ( (pSchema.getAnnotationValue("indexed") != null) + && (pSchema.getAnnotationValue("indexed").equalsIgnoreCase("true")) ) { + if (indexedVal.length() > 0) { + indexedVal.append(","); + } + indexedVal.append(pSchema.getName()); + } + } + + if (searchableVal.length() > 0) { + annotations.put("searchable", searchableVal.toString()); + } + if (indexedVal.length() > 0) { + annotations.put("indexedprops", indexedVal.toString()); + } + } + + private void addCommonProps() throws SchemaProviderException { + addCommonProperty("aai-uuid", false, true, "string", "true"); + addCommonProperty("last-mod-source-of-truth", false, false, "string", "false"); + addCommonProperty("aai-node-type", false, false, "string", "false"); + addCommonProperty("aai-created-ts", false, false, "string", "false"); + addCommonProperty("aai-unique-key", false, false, "string", "false"); + addCommonProperty("aai-last-mod-ts", false, false, "string", "false"); + addCommonProperty("source-of-truth", false, false, "string", "false"); + addCommonProperty("aai-uri", false, false, "string", "false"); + + } + + private void addCommonProperty(String name, boolean req, boolean unique, String type, String indexed) throws SchemaProviderException { + JsonPropertySchema pSchema = new JsonPropertySchema(); + pSchema.setName(name); + pSchema.setRequired(req); + pSchema.setUnique(unique); + pSchema.setDataType(type); + pSchema.setDescription(""); + pSchema.setDefaultValue(""); + + Map<String,String> propAnnotations = new HashMap<String,String>(); + propAnnotations.put("indexed", indexed); + propAnnotations.put("searchable", "false"); + propAnnotations.put("source_of_truth_type", "AAI"); + + pSchema.setAnnotations(propAnnotations); + + FromJsonPropertySchema propSchema = new FromJsonPropertySchema(); + propSchema.fromJson(pSchema, true, null); + + properties.put(name, propSchema); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/JsonSchemaProvider.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/JsonSchemaProvider.java new file mode 100644 index 00000000..a947eac4 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/JsonSchemaProvider.java @@ -0,0 +1,235 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Scanner; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.schemaif.SchemaProvider; +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.SchemaProviderMsgs; +import org.onap.aai.schemaif.definitions.EdgeSchema; +import org.onap.aai.schemaif.definitions.VertexSchema; +import org.onap.aai.schemaif.json.definitions.JsonEdgeSchema; +import org.onap.aai.schemaif.json.definitions.JsonSchema; +import org.onap.aai.schemaif.json.definitions.JsonVertexSchema; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + + +public class JsonSchemaProvider implements SchemaProvider { + Logger logger = LoggerFactory.getInstance().getLogger(JsonSchemaProvider.class.getName()); + + private JsonSchemaProviderConfig config; + private Map<String,SchemaInstance> schemaCache = new ConcurrentHashMap<>(); + private RestTemplate restTemplate = null; + + public JsonSchemaProvider(JsonSchemaProviderConfig config) { + this.config = config; + + SecureClientHttpRequestFactory fac = new SecureClientHttpRequestFactory(config); + fac.setBufferRequestBody(false); + this.restTemplate = new RestTemplate(fac); + } + + @Override + public void loadSchema() throws SchemaProviderException { + // Load the latest schema version + fetchSchemaVersion(getLatestSchemaVersion()); + } + + @Override + public String getLatestSchemaVersion() throws SchemaProviderException { + return "v0"; + } + + @Override + public VertexSchema getVertexSchema(String vertexName, String schemaVersion) throws SchemaProviderException { + SchemaInstance inst = getSchemaVersion(schemaVersion); + return inst.getVertexSchema(vertexName); + } + + @Override + public EdgeSchema getEdgeSchema(String edgeType, String sourceVertex, String targetVertex, String version) + throws SchemaProviderException { + SchemaInstance inst = getSchemaVersion(version); + return inst.getEdgeSchema(sourceVertex, targetVertex, edgeType); + } + + @Override + public Set<EdgeSchema> getAdjacentEdgeSchema(String vertexType, String version) throws SchemaProviderException { + SchemaInstance inst = getSchemaVersion(version); + + Set<EdgeSchema> edgeList = inst.getEdgeSchema(vertexType); + if (edgeList == null) { + edgeList = new HashSet<EdgeSchema>(); + } + + return edgeList; + } + + @Override + public Set<EdgeSchema> getEdgeSchemaForSourceTarget(String sourceType, String targetType, String version) + throws SchemaProviderException { + SchemaInstance inst = getSchemaVersion(version); + + if (inst == null) { + throw new SchemaProviderException("Unable to find schema version " + version); + } + + Set<EdgeSchema> edgeList = inst.getEdgeSchemas(sourceType, targetType); + if (edgeList == null) { + edgeList = new HashSet<EdgeSchema>(); + } + + return edgeList; + } + + public void loadSchema(String payload, String version) throws SchemaProviderException { + JsonSchema jsonSchema = JsonSchema.fromJson(payload); + SchemaInstance schemaInst = new SchemaInstance(); + + for (JsonVertexSchema jsonVertex : jsonSchema.getNodeTypes()) { + FromJsonVertexSchema vSchema = new FromJsonVertexSchema(); + vSchema.fromJson(jsonVertex, jsonSchema.getDataTypes(), jsonSchema.getCommonProperties()); + schemaInst.addVertex(vSchema); + } + + for (JsonEdgeSchema jsonEdge : jsonSchema.getRelationshipTypes()) { + FromJsonEdgeSchema eSchema = new FromJsonEdgeSchema(); + eSchema.fromJson(jsonEdge); + schemaInst.addEdge(eSchema); + } + + schemaCache.put(version, schemaInst); + } + + private synchronized void fetchSchemaVersion(String version) throws SchemaProviderException { + if (schemaCache.get(version) != null) { + return; + } + + + String url = config.getSchemaServiceBaseUrl() + "/" + version; + + HttpHeaders headers = new HttpHeaders(); + headers.put("X-FromAppId", Arrays.asList(config.getServiceName())); + headers.put("X-TransactionId", Arrays.asList(java.util.UUID.randomUUID().toString())); + headers.setAccept(Arrays.asList(org.springframework.http.MediaType.APPLICATION_OCTET_STREAM)); + + HttpEntity <String> entity = new HttpEntity<String>(headers); + + ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.GET, entity, byte[].class); + + + if (response.getStatusCodeValue() == HttpStatus.NOT_FOUND.value()) { + logger.warn(SchemaProviderMsgs.SCHEMA_LOAD_ERROR, "version " + version + " not found"); + throw new SchemaProviderException("Schema version " + version + " not found"); + } + else if (response.getStatusCodeValue() != HttpStatus.OK.value()) { + logger.error(SchemaProviderMsgs.SCHEMA_LOAD_ERROR, "failed to load version " + version + ": " + response.getBody()); + throw new SchemaProviderException("Error getting schema version " + version + ":" + response.getBody()); + } + + try { + SchemaServiceResponse resp = SchemaServiceResponse.fromJson(unzipAndGetJSONString(response)); + loadSchema(resp.getData().toJson(), version); + } + catch (Exception ex) { + StringWriter writer = new StringWriter(); + PrintWriter printWriter = new PrintWriter(writer); + ex.printStackTrace(printWriter); + logger.error(SchemaProviderMsgs.SCHEMA_LOAD_ERROR, "failed to load version " + version + ": " + + response.getBody() + "\n" + writer.toString()); + throw new SchemaProviderException("Error loading schema version " + version + ":" + ex.getMessage()); + + } + + logger.info(SchemaProviderMsgs.LOADED_SCHEMA_FILE, version); + } + + private String unzipAndGetJSONString(ResponseEntity<byte[]> response) throws IOException { + StringBuffer sb = new StringBuffer(""); + + ZipInputStream zipStream = null; + try { + + zipStream = new ZipInputStream(new ByteArrayInputStream(response.getBody())); + ZipEntry entry = null; + while ((entry = zipStream.getNextEntry()) != null) { + Scanner sc = new Scanner(zipStream); + while (sc.hasNextLine()) { + sb.append(sc.nextLine()); + } + + } + } finally { + try { + zipStream.closeEntry(); + zipStream.close(); + } catch (Exception e) { + logger.warn(SchemaProviderMsgs.SCHEMA_LOAD_ERROR, e.toString()); + + } + } + + return sb.toString(); + } + + private SchemaInstance getSchemaVersion(String version) throws SchemaProviderException { + // TODO: For now, we are only supporting a single version of the schema. Load that + // version regardless of what the client asks for. + String versionToLoad = getLatestSchemaVersion(); + SchemaInstance inst = schemaCache.get(versionToLoad); + + if (inst == null) { + fetchSchemaVersion(versionToLoad); + inst = schemaCache.get(versionToLoad); + if (inst == null) { + throw new SchemaProviderException("Unable to find schema version " + versionToLoad); + } + } + + return inst; + } + + @Override + public Map<String, VertexSchema> getVertexMap(String schemaVersion) throws SchemaProviderException { + return getSchemaVersion(schemaVersion).getVertexMap(); + } + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/JsonSchemaProviderConfig.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/JsonSchemaProviderConfig.java new file mode 100644 index 00000000..3a235f63 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/JsonSchemaProviderConfig.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json; + + +public class JsonSchemaProviderConfig { + + private String schemaServiceBaseUrl; + private String schemaServiceCertFile; + private String schemaServiceCertPwd; + private String serviceName; + + public String getSchemaServiceBaseUrl() { + return schemaServiceBaseUrl; + } + public void setSchemaServiceBaseUrl(String schemaServiceBaseUrl) { + this.schemaServiceBaseUrl = schemaServiceBaseUrl; + } + + public String getSchemaServiceCertFile() { + return schemaServiceCertFile; + } + public void setSchemaServiceCertFile(String schemaServiceCertFile) { + this.schemaServiceCertFile = schemaServiceCertFile; + } + + public String getSchemaServiceCertPwd() { + return schemaServiceCertPwd; + } + public void setSchemaServiceCertPwd(String schemaServiceCertPwd) { + this.schemaServiceCertPwd = schemaServiceCertPwd; + } + + public String getServiceName() { + return serviceName; + } + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/SchemaInstance.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/SchemaInstance.java new file mode 100644 index 00000000..77a1c56b --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/SchemaInstance.java @@ -0,0 +1,121 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.definitions.EdgeSchema; +import org.onap.aai.schemaif.definitions.VertexSchema; + +public class SchemaInstance { + // vertex-name -> vertex-schema + private Map<String, VertexSchema> vertexMap = new HashMap<>(); + + // source:target:type -> edge-schema + private Map<String, EdgeSchema> edgeKeyMap = new HashMap<>(); + + // source:target -> edge-schema + private Map<String, Set<EdgeSchema>> edgeSourceTargetMap = new HashMap<>(); + + // vertex-name -> edge-schema + private Map<String, Set<EdgeSchema>> vertexEdgeMap = new HashMap<>(); + + public VertexSchema getVertexSchema(String vertexName) { + return vertexMap.get(vertexName.toLowerCase()); + } + + public EdgeSchema getEdgeSchema(String source, String target, String type) { + return edgeKeyMap.get(generateEdgeKey(source, target, type)); + } + + public Set<EdgeSchema> getEdgeSchemas(String source, String target) { + return edgeSourceTargetMap.get(source.toLowerCase() + ":" + target.toLowerCase()); + } + + public Set<EdgeSchema> getEdgeSchema(String vertexName) { + return vertexEdgeMap.get(vertexName.toLowerCase()); + } + + public void addVertex(VertexSchema v) { + vertexMap.put(v.getName().toLowerCase(), v); + } + + public void addEdge(EdgeSchema e) throws SchemaProviderException { + if (e.getSource().equals(FromJsonEdgeSchema.WILDCARD_CHAR) || + e.getTarget().equals(FromJsonEdgeSchema.WILDCARD_CHAR)) { + // Handle wildcard edges + for (VertexSchema vertex : vertexMap.values()) { + addWildcardEdge(e, vertex); + } + } + else { + addEdgeInternal(e); + } + } + + private void addWildcardEdge(EdgeSchema e, VertexSchema vertex) throws SchemaProviderException { + FromJsonEdgeSchema newEdge = new FromJsonEdgeSchema(e); + newEdge.replaceWildcard(vertex.getName()); + addEdgeInternal(newEdge); + } + + private void addEdgeInternal(EdgeSchema e) { + edgeKeyMap.put(generateEdgeKey(e.getSource(), e.getTarget(), e.getName()), e); + + Set<EdgeSchema> edgeListSource = vertexEdgeMap.get(e.getSource().toLowerCase()); + Set<EdgeSchema> edgeListTarget = vertexEdgeMap.get(e.getTarget().toLowerCase()); + + if (edgeListSource == null) { + edgeListSource = new HashSet<EdgeSchema>(); + } + if (edgeListTarget == null) { + edgeListTarget = new HashSet<EdgeSchema>(); + } + + edgeListSource.add(e); + edgeListTarget.add(e); + vertexEdgeMap.put(e.getSource().toLowerCase(), edgeListSource); + vertexEdgeMap.put(e.getTarget().toLowerCase(), edgeListTarget); + + String sourceTargetKey = e.getSource().toLowerCase() + ":" + e.getTarget().toLowerCase(); + Set<EdgeSchema> edgeList = edgeSourceTargetMap.get(sourceTargetKey); + if (edgeList == null) { + edgeList = new HashSet<EdgeSchema>(); + } + + edgeList.add(e); + edgeSourceTargetMap.put(sourceTargetKey, edgeList); + } + + private String generateEdgeKey(String source, String target, String type) { + String key = source + ":" + target + ":" + type; + return key.toLowerCase(); + } + + public Map<String, VertexSchema> getVertexMap() { + return vertexMap; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/SchemaServiceResponse.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/SchemaServiceResponse.java new file mode 100644 index 00000000..7fa123a5 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/SchemaServiceResponse.java @@ -0,0 +1,67 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json; + +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.json.definitions.JsonSchema; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; + +public class SchemaServiceResponse { + public static final String SCHEMA_TYPE_OXM = "oxm"; + public static final String SCHEMA_TYPE_JSON = "json"; + + private static final Gson gson = new GsonBuilder().create(); + + @SerializedName("schema-version") + private String version; + + @SerializedName("schema-content") + private JsonSchema data; + + public String getVersion() { + return version; + } + + public JsonSchema getData() { + return data; + } + + public String toJson() { + return gson.toJson(this); + } + + public static SchemaServiceResponse fromJson(String json) throws SchemaProviderException { + try { + if (json == null || json.isEmpty()) { + throw new SchemaProviderException("Empty schema-service response"); + } + + return gson.fromJson(json, SchemaServiceResponse.class); + } catch (Exception ex) { + throw new SchemaProviderException("Invalid response from schema service: " + ex.getMessage()); + } + } + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/SecureClientHttpRequestFactory.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/SecureClientHttpRequestFactory.java new file mode 100644 index 00000000..0b48a36c --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/SecureClientHttpRequestFactory.java @@ -0,0 +1,126 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 European Software Marketing Ltd. + * ================================================================================ + * 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.aai.schemaif.json; + + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.security.KeyStore; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.springframework.http.client.SimpleClientHttpRequestFactory; + + +public class SecureClientHttpRequestFactory extends SimpleClientHttpRequestFactory { + + private static final String SSL_PROTOCOL = "TLS"; + private static final String KEYSTORE_ALGORITHM = "SunX509"; + private static final String KEYSTORE_TYPE = "PKCS12"; + private JsonSchemaProviderConfig config; + + + public SecureClientHttpRequestFactory(JsonSchemaProviderConfig config) { + super(); + this.config = config; + } + + @Override + protected void prepareConnection(final HttpURLConnection connection, final String httpMethod) + throws IOException { + if (connection instanceof HttpsURLConnection) { + ((HttpsURLConnection) connection) + .setSSLSocketFactory(getSSLContext().getSocketFactory()); + ((HttpsURLConnection) connection).setHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String str, SSLSession sslSession) { + return true; + } + }); + } else { + + throw new IOException(); + } + super.prepareConnection(connection, httpMethod); + } + + protected SSLContext getSSLContext() throws IOException { + try { + TrustManager[] trustAllCerts = null; + + // We aren't validating certificates, so create a trust manager that + // does + // not validate certificate chains. + trustAllCerts = new TrustManager[] {new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + }}; + + SSLContext ctx = SSLContext.getInstance(SSL_PROTOCOL); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM); + KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE); + + char[] pwd = null; + if (config.getSchemaServiceCertPwd()!= null) { + pwd = config.getSchemaServiceCertPwd().toCharArray(); + } + + if (config.getSchemaServiceCertFile() != null) { + FileInputStream fin =null; + try { + fin = new FileInputStream(config.getSchemaServiceCertFile()); + + // Load the keystore and initialize the key manager factory. + ks.load(fin, pwd); + kmf.init(ks, pwd); + + ctx.init(kmf.getKeyManagers(), trustAllCerts, null); + }finally { + fin.close(); + } + } else { + ctx.init(null, trustAllCerts, null); + } + + return ctx; + } catch (Exception e) { + throw new IOException("Problem with getting the SSL Context::" + e.getMessage(), e); + } + + } + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/DataTypeDefinition.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/DataTypeDefinition.java new file mode 100644 index 00000000..93c67bdc --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/DataTypeDefinition.java @@ -0,0 +1,125 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json.definitions; + +import java.util.List; + +import org.onap.aai.schemaif.SchemaProviderException; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class DataTypeDefinition { + private static final Gson gson = new GsonBuilder().create(); + + private String name; + private String description; + private List<JsonPropertySchema> properties; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public List<JsonPropertySchema> getProperties() { + return properties; + } + + public void setProperties(List<JsonPropertySchema> properties) { + this.properties = properties; + } + + public void validate() throws SchemaProviderException { + if ( (getName() == null) || (getName().isEmpty()) ) { + throw new SchemaProviderException("Type definition missing a name"); + } + + if (getProperties() != null) { + for (JsonPropertySchema propSchema : getProperties()) { + propSchema.validate(); + } + } + } + + public String toJson() { + return gson.toJson(this); + } + + public static DataTypeDefinition fromJson(String json) { + return gson.fromJson(json, DataTypeDefinition.class); + } + + @Override + public String toString() { + return "DataTypeDefinition [name=" + name + ", description=" + description + ", properties=" + + properties + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((properties == null) ? 0 : properties.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DataTypeDefinition other = (DataTypeDefinition) obj; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (properties == null) { + if (other.properties != null) + return false; + } else if (!properties.equals(other.properties)) + return false; + return true; + } + + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonEdgeSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonEdgeSchema.java new file mode 100644 index 00000000..ffbc54de --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonEdgeSchema.java @@ -0,0 +1,135 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json.definitions; + + +import java.util.Map; + +import org.onap.aai.schemaif.SchemaProviderException; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class JsonEdgeSchema { + private static final Gson gson = new GsonBuilder().create(); + + private String from; + private String to; + private String label; + private Map<String,String> annotations; + + public String getFrom() { + return from; + } + public void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + public void setTo(String to) { + this.to = to; + } + + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } + + public Map<String,String> getAnnotations() { + return annotations; + } + public void setAnnotations(Map<String,String> annotations) { + this.annotations = annotations; + } + + public void validate() throws SchemaProviderException { + if ( (getTo() == null) || (getTo().isEmpty()) ) { + throw new SchemaProviderException("Edge definition missing 'to'"); + } + + if ( (getFrom() == null) || (getFrom().isEmpty()) ) { + throw new SchemaProviderException("Edge definition missing 'from'"); + } + + if ( (getLabel() == null) || (getLabel().isEmpty()) ) { + throw new SchemaProviderException("Edge definition missing 'label'"); + } + } + + public String toJson() { + return gson.toJson(this); + } + + public static JsonEdgeSchema fromJson(String json) { + return gson.fromJson(json, JsonEdgeSchema.class); + } + @Override + public String toString() { + return "JsonEdgeSchema [from=" + from + ", to=" + to + ", label=" + label + ", annotations=" + + annotations + "]"; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((annotations == null) ? 0 : annotations.hashCode()); + result = prime * result + ((from == null) ? 0 : from.hashCode()); + result = prime * result + ((label == null) ? 0 : label.hashCode()); + result = prime * result + ((to == null) ? 0 : to.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + JsonEdgeSchema other = (JsonEdgeSchema) obj; + if (annotations == null) { + if (other.annotations != null) + return false; + } else if (!annotations.equals(other.annotations)) + return false; + if (from == null) { + if (other.from != null) + return false; + } else if (!from.equals(other.from)) + return false; + if (label == null) { + if (other.label != null) + return false; + } else if (!label.equals(other.label)) + return false; + if (to == null) { + if (other.to != null) + return false; + } else if (!to.equals(other.to)) + return false; + return true; + } + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonPropertySchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonPropertySchema.java new file mode 100644 index 00000000..b6934eb8 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonPropertySchema.java @@ -0,0 +1,192 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json.definitions; + +import java.util.Map; + +import org.onap.aai.schemaif.SchemaProviderException; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; + +public class JsonPropertySchema { + private static final Gson gson = new GsonBuilder().create(); + + private String name; + private Boolean required; + private Boolean unique; + + @SerializedName("type") + private String dataType; + + private String description; + + @SerializedName("default") + private String defaultValue; + + private Map<String,String> annotations; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Boolean getRequired() { + return required; + } + + public void setRequired(Boolean required) { + this.required = required; + } + + public Boolean getUnique() { + return unique; + } + + public void setUnique(Boolean unique) { + this.unique = unique; + } + + public String getDataType() { + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = dataType; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Map<String,String> getAnnotations() { + return annotations; + } + + public void setAnnotations(Map<String,String> annotations) { + this.annotations = annotations; + } + + public void validate() throws SchemaProviderException { + if ( (getName() == null) || (getName().isEmpty()) ) { + throw new SchemaProviderException(getName() + " property has no name"); + } + + if ( (getDataType() == null) || (getDataType().isEmpty()) ) { + throw new SchemaProviderException(getName() + " property has no type"); + } + } + + + public String toJson() { + return gson.toJson(this); + } + + public static JsonVertexSchema fromJson(String json) { + return gson.fromJson(json, JsonVertexSchema.class); + } + + @Override + public String toString() { + return "JsonPropertySchema [name=" + name + ", required=" + required + ", unique=" + unique + + ", dataType=" + dataType + ", description=" + description + ", defaultValue=" + + defaultValue + ", annotations=" + annotations + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((annotations == null) ? 0 : annotations.hashCode()); + result = prime * result + ((dataType == null) ? 0 : dataType.hashCode()); + result = prime * result + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((required == null) ? 0 : required.hashCode()); + result = prime * result + ((unique == null) ? 0 : unique.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + JsonPropertySchema other = (JsonPropertySchema) obj; + if (annotations == null) { + if (other.annotations != null) + return false; + } else if (!annotations.equals(other.annotations)) + return false; + if (dataType == null) { + if (other.dataType != null) + return false; + } else if (!dataType.equals(other.dataType)) + return false; + if (defaultValue == null) { + if (other.defaultValue != null) + return false; + } else if (!defaultValue.equals(other.defaultValue)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (required == null) { + if (other.required != null) + return false; + } else if (!required.equals(other.required)) + return false; + if (unique == null) { + if (other.unique != null) + return false; + } else if (!unique.equals(other.unique)) + return false; + return true; + } + + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonSchema.java new file mode 100644 index 00000000..b9cacb87 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonSchema.java @@ -0,0 +1,167 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json.definitions; + +import java.util.List; + +import org.onap.aai.schemaif.SchemaProviderException; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; + +public class JsonSchema { + private static final Gson gson = new GsonBuilder().create(); + + @SerializedName("relationship_types") + private List<JsonEdgeSchema> relationshipTypes; + + @SerializedName("node_types") + private List<JsonVertexSchema> nodeTypes; + + @SerializedName("data_types") + private List<DataTypeDefinition> dataTypes; + + @SerializedName("common_node_properties") + private List<JsonPropertySchema> commonNodeProps; + + + public void setRelationshipTypes(List<JsonEdgeSchema> relationshipTypes) { + this.relationshipTypes = relationshipTypes; + } + + public void setNodeTypes(List<JsonVertexSchema> nodeTypes) { + this.nodeTypes = nodeTypes; + } + + public void setDataTypes(List<DataTypeDefinition> dataTypes) { + this.dataTypes = dataTypes; + } + + public List<JsonEdgeSchema> getRelationshipTypes() { + return relationshipTypes; + } + + public List<JsonVertexSchema> getNodeTypes() { + return nodeTypes; + } + + public List<DataTypeDefinition> getDataTypes() { + return dataTypes; + } + + public List<JsonPropertySchema> getCommonProperties() { + return commonNodeProps; + } + + public void setCommonProperties(List<JsonPropertySchema> properties) { + this.commonNodeProps = properties; + } + + public void validate() throws SchemaProviderException { + if (getNodeTypes() != null) { + for (JsonVertexSchema vertexSchema : getNodeTypes()) { + vertexSchema.validate(); + } + } + + // Validate edges + if (getRelationshipTypes() != null) { + for (JsonEdgeSchema edgeSchema : getRelationshipTypes()) { + edgeSchema.validate(); + } + } + + // Validate data types + if (getDataTypes() != null) { + for (DataTypeDefinition typeSchema : getDataTypes()) { + typeSchema.validate(); + } + } + } + + public String toJson() { + return gson.toJson(this); + } + + public static JsonSchema fromJson(String json) throws SchemaProviderException { + try { + if (json == null || json.isEmpty()) { + throw new SchemaProviderException("Empty schema definition"); + } + + return gson.fromJson(json, JsonSchema.class); + } catch (Exception ex) { + throw new SchemaProviderException("Invalid json: " + ex.getMessage()); + } + } + + @Override + public String toString() { + return "JsonSchema [relationshipTypes=" + relationshipTypes + ", nodeTypes=" + nodeTypes + + ", dataTypes=" + dataTypes + ", commonNodeProps=" + commonNodeProps + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((commonNodeProps == null) ? 0 : commonNodeProps.hashCode()); + result = prime * result + ((dataTypes == null) ? 0 : dataTypes.hashCode()); + result = prime * result + ((nodeTypes == null) ? 0 : nodeTypes.hashCode()); + result = prime * result + ((relationshipTypes == null) ? 0 : relationshipTypes.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + JsonSchema other = (JsonSchema) obj; + if (commonNodeProps == null) { + if (other.commonNodeProps != null) + return false; + } else if (!commonNodeProps.equals(other.commonNodeProps)) + return false; + if (dataTypes == null) { + if (other.dataTypes != null) + return false; + } else if (!dataTypes.equals(other.dataTypes)) + return false; + if (nodeTypes == null) { + if (other.nodeTypes != null) + return false; + } else if (!nodeTypes.equals(other.nodeTypes)) + return false; + if (relationshipTypes == null) { + if (other.relationshipTypes != null) + return false; + } else if (!relationshipTypes.equals(other.relationshipTypes)) + return false; + return true; + } + + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonVertexSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonVertexSchema.java new file mode 100644 index 00000000..87a1eac7 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/json/definitions/JsonVertexSchema.java @@ -0,0 +1,141 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.json.definitions; + +import java.util.List; +import java.util.Map; + +import org.onap.aai.schemaif.SchemaProviderException; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class JsonVertexSchema { + private static final Gson gson = new GsonBuilder().create(); + + private String name; + private String description; + private List<JsonPropertySchema> properties; + private Map<String,String> annotations; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public List<JsonPropertySchema> getProperties() { + return properties; + } + + public void setProperties(List<JsonPropertySchema> properties) { + this.properties = properties; + } + + public Map<String,String> getAnnotations() { + return annotations; + } + + public void setAnnotations(Map<String,String> annotations) { + this.annotations = annotations; + } + + public void validate() throws SchemaProviderException { + if ( (getName() == null) || (getName().isEmpty()) ) { + throw new SchemaProviderException("Node definition missing a name"); + } + + if (getProperties() != null) { + for (JsonPropertySchema propSchema : getProperties()) { + propSchema.validate(); + } + } + } + + public String toJson() { + return gson.toJson(this); + } + + public static JsonVertexSchema fromJson(String json) { + return gson.fromJson(json, JsonVertexSchema.class); + } + + @Override + public String toString() { + return "JsonVertexSchema [name=" + name + ", description=" + description + ", properties=" + + properties + ", annotations=" + annotations + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((annotations == null) ? 0 : annotations.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((properties == null) ? 0 : properties.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + JsonVertexSchema other = (JsonVertexSchema) obj; + if (annotations == null) { + if (other.annotations != null) + return false; + } else if (!annotations.equals(other.annotations)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (properties == null) { + if (other.properties != null) + return false; + } else if (!properties.equals(other.properties)) + return false; + return true; + } + + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/EdgePropsConfiguration.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/EdgePropsConfiguration.java new file mode 100644 index 00000000..bd30e77e --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/EdgePropsConfiguration.java @@ -0,0 +1,42 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.oxm; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component +@PropertySource(value = "file:${edgeprops.ingest.file}", ignoreResourceNotFound = true) +public class EdgePropsConfiguration { + + @Value("${edgePropsDir}") + private String edgePropsDir; + + public String getEdgePropsDir() { + return edgePropsDir; + } + + public void setEdgePropsDir(String edgePropsDir) { + this.edgePropsDir = edgePropsDir; + } + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/FromOxmEdgeSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/FromOxmEdgeSchema.java new file mode 100644 index 00000000..336b6d9e --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/FromOxmEdgeSchema.java @@ -0,0 +1,75 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.oxm; + +import java.util.HashMap; + +import org.onap.aai.edges.EdgeRule; +import org.onap.aai.edges.enums.EdgeProperty; +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.definitions.EdgeSchema; +import org.onap.aai.schemaif.definitions.PropertySchema; +import org.onap.aai.schemaif.definitions.types.DataType; + + +public class FromOxmEdgeSchema extends EdgeSchema { + + public void fromEdgeRule(EdgeRule edgeRule) throws SchemaProviderException { + name = edgeRule.getLabel(); + source = edgeRule.getFrom(); + target = edgeRule.getTo(); + + switch (edgeRule.getMultiplicityRule()) { + case MANY2MANY: + multiplicity = Multiplicity.MANY_2_MANY; + break; + case MANY2ONE: + multiplicity = Multiplicity.MANY_2_ONE; + break; + case ONE2MANY: + multiplicity = Multiplicity.ONE_2_MANY; + break; + case ONE2ONE: + multiplicity = Multiplicity.ONE_2_ONE; + break; + } + + annotations = new HashMap<String,String>(); + properties = new HashMap<String,PropertySchema>(); + + // TODO: For now these are hard-coded ... should read them from a config file or something + annotations.put(EdgeProperty.CONTAINS.toString().toLowerCase(), edgeRule.getContains()); + annotations.put(EdgeProperty.DELETE_OTHER_V.toString().toLowerCase(), edgeRule.getDeleteOtherV()); + annotations.put(EdgeProperty.PREVENT_DELETE.toString().toLowerCase(), edgeRule.getPreventDelete()); + + FromOxmPropertySchema pSchema = new FromOxmPropertySchema(); + pSchema.fromRelationship(EdgeProperty.CONTAINS.toString(), DataType.Type.STRING); + properties.put(EdgeProperty.CONTAINS.toString().toLowerCase(), pSchema); + + pSchema = new FromOxmPropertySchema(); + pSchema.fromRelationship(EdgeProperty.DELETE_OTHER_V.toString(), DataType.Type.STRING); + properties.put(EdgeProperty.DELETE_OTHER_V.toString().toLowerCase(), pSchema); + + pSchema = new FromOxmPropertySchema(); + pSchema.fromRelationship(EdgeProperty.PREVENT_DELETE.toString(), DataType.Type.STRING); + properties.put(EdgeProperty.PREVENT_DELETE.toString().toLowerCase(), pSchema); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/FromOxmPropertySchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/FromOxmPropertySchema.java new file mode 100644 index 00000000..2174bce2 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/FromOxmPropertySchema.java @@ -0,0 +1,141 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.oxm; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.persistence.dynamic.DynamicType; +import org.eclipse.persistence.internal.helper.DatabaseField; +import org.eclipse.persistence.mappings.DatabaseMapping; +import org.eclipse.persistence.oxm.XMLField; +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.definitions.PropertySchema; +import org.onap.aai.schemaif.definitions.types.BooleanDataType; +import org.onap.aai.schemaif.definitions.types.DataType; +import org.onap.aai.schemaif.definitions.types.FloatDataType; +import org.onap.aai.schemaif.definitions.types.IntDataType; +import org.onap.aai.schemaif.definitions.types.LongDataType; +import org.onap.aai.schemaif.definitions.types.StringDataType; + + +public class FromOxmPropertySchema extends PropertySchema { + + // Handle vertex properties from OXM + public void fromOxm(DatabaseMapping mapping, DynamicType dynType, boolean reserved) throws SchemaProviderException { + DatabaseField field = mapping.getField(); + if (field.getName().contains("/")) { + name = field.getName().substring(0, field.getName().indexOf("/")); + } else { + name = field.getName(); + } + + defaultValue = mapping.getProperties().get("defaultValue") == null ? "" + : mapping.getProperties().get("defaultValue").toString(); + + if (isPrimaryKeyOxm(name, dynType)) { + unique = true; + required = true; + } + else { + required = ((XMLField) field).isRequired(); + unique = false; + } + + isReserved = reserved; + + String oxmType = ((XMLField) field).getTypeName() != null ? ((XMLField) field).getTypeName() : ""; + if (!mapping.isAbstractDirectMapping()) { + // treat complex types as string blobs in oxm + dataType = new StringDataType(); + } else { + if (oxmType.equalsIgnoreCase("java.lang.String")) { + dataType = new StringDataType(); + } else if (oxmType.equalsIgnoreCase("java.lang.Long")) { + dataType = new LongDataType(); + } else if (oxmType.equalsIgnoreCase("java.lang.Boolean")) { + dataType = new BooleanDataType(); + } else if (oxmType.equalsIgnoreCase("java.lang.Integer")) { + dataType = new IntDataType(); + } else if (oxmType.equalsIgnoreCase("java.lang.Float")) { + dataType = new FloatDataType(); + } else { + throw new SchemaProviderException("Invalid OXM property type: " + oxmType); + } + } + + // Check annotations + annotations = new HashMap<String,String>(); + Map<String, Object> oxmProps = mapping.getProperties(); + for (Map.Entry<String, Object> entry : oxmProps.entrySet()) { + if (entry.getValue() instanceof String) { + annotations.put(entry.getKey().toLowerCase(), (String)entry.getValue()); + } + } + } + + // Handle edge properties from DBEdgeRules + public void fromRelationship(String propName, DataType.Type propDataType) throws SchemaProviderException { + name = propName; + required = false; + defaultValue = ""; + unique = false; + annotations = new HashMap<String,String>(); + + switch (propDataType) { + case STRING: + dataType = new StringDataType(); + break; + case INT: + dataType = new IntDataType(); + break; + case FLOAT: + dataType = new FloatDataType(); + break; + case LONG: + dataType = new LongDataType(); + break; + case BOOL: + dataType = new BooleanDataType(); + break; + default: + throw new SchemaProviderException("Invalid EdgeRule property type: " + propDataType); + } + } + + private boolean isPrimaryKeyOxm(String propName, DynamicType dynType) { + List<String> primaryKeyList = dynType.getDescriptor().getPrimaryKeyFieldNames(); + if ( (primaryKeyList == null) || (primaryKeyList.size() == 0) ) { + return false; + } + + for (String key : primaryKeyList) { + String keyName = key.substring(0, key.indexOf('/')); + if (keyName.equals(propName)) { + return true; + } + } + + return false; + } + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/FromOxmVertexSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/FromOxmVertexSchema.java new file mode 100644 index 00000000..6083429b --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/FromOxmVertexSchema.java @@ -0,0 +1,95 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.oxm; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.persistence.dynamic.DynamicType; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import org.eclipse.persistence.mappings.DatabaseMapping; +import org.eclipse.persistence.oxm.mappings.XMLAnyCollectionMapping; +import org.eclipse.persistence.oxm.mappings.XMLAnyObjectMapping; +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.definitions.PropertySchema; +import org.onap.aai.schemaif.definitions.VertexSchema; + +import com.google.common.base.CaseFormat; + +public class FromOxmVertexSchema extends VertexSchema { + public void fromOxm(String vertexType, DynamicJAXBContext jaxbContext, HashMap<String, DynamicType> xmlElementLookup) throws SchemaProviderException { + name = vertexType; + properties = new HashMap<String,PropertySchema>(); + annotations = new HashMap<String,String>(); + + String javaTypeName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, vertexType); + DynamicType modelObjectType = jaxbContext.getDynamicType(javaTypeName); + + if (modelObjectType == null) { + // Try to lookup by xml root element by exact match + modelObjectType = xmlElementLookup.get(vertexType); + } + + if (modelObjectType == null) { + // Try to lookup by xml root element by lowercase + modelObjectType = xmlElementLookup.get(vertexType.toLowerCase()); + } + + if (modelObjectType == null) { + // Direct lookup as java-type name + modelObjectType = jaxbContext.getDynamicType(vertexType); + } + + if (modelObjectType == null) { + // Vertex isn't found in the OXM + throw new SchemaProviderException("Vertex " + vertexType + " not found in OXM"); + } + + // Check annotations + Map<String, Object> oxmProps = modelObjectType.getDescriptor().getProperties(); + for (Map.Entry<String, Object> entry : oxmProps.entrySet()) { + if (entry.getValue() instanceof String) { + annotations.put(entry.getKey().toLowerCase(), (String)entry.getValue()); + } + } + + // Regular props + for (DatabaseMapping mapping : modelObjectType.getDescriptor().getMappings()) { + if (mapping instanceof XMLAnyObjectMapping) + continue; + if(mapping instanceof XMLAnyCollectionMapping) + continue; + FromOxmPropertySchema propSchema = new FromOxmPropertySchema(); + propSchema.fromOxm(mapping, modelObjectType, false); + properties.put(propSchema.getName().toLowerCase(), propSchema); + } + + // Reserved Props + final DynamicType reservedType = jaxbContext.getDynamicType("ReservedPropNames"); + for (DatabaseMapping mapping : reservedType.getDescriptor().getMappings()) { + if (mapping.isAbstractDirectMapping()) { + FromOxmPropertySchema propSchema = new FromOxmPropertySchema(); + propSchema.fromOxm(mapping, reservedType, true); + properties.put(propSchema.getName().toLowerCase(), propSchema); + } + } + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/OxmEdgeRulesLoader.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/OxmEdgeRulesLoader.java new file mode 100644 index 00000000..39e7039f --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/OxmEdgeRulesLoader.java @@ -0,0 +1,246 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.oxm; + +import com.google.common.collect.Multimap; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.apache.commons.io.IOUtils; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.edges.EdgeRule; +import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.SchemaProviderMsgs; +import org.onap.aai.setup.SchemaVersion; +import org.onap.aai.setup.Translator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class OxmEdgeRulesLoader { + + private static Translator translator; + private static EdgeIngestor edgeIngestor; + + private static EdgePropsConfiguration edgePropsConfiguration; + + private static Map<String, RelationshipSchema> versionContextMap = new ConcurrentHashMap<>(); + + static final Pattern versionPattern = Pattern.compile("(?i)v(\\d*)"); + static final String propsPrefix = "edge_properties_"; + static final String propsSuffix = ".json"; + final static Pattern propsFilePattern = Pattern.compile(propsPrefix + "(.*)" + propsSuffix); + final static Pattern propsVersionPattern = Pattern.compile("(?i)v\\d*"); + + private static org.onap.aai.cl.api.Logger logger = + LoggerFactory.getInstance().getLogger(OxmEdgeRulesLoader.class.getName()); + + private OxmEdgeRulesLoader() {} + + /** + * This constructor presents an awkward marrying of Spring bean creation and static method use. This + * is technical debt that will need fixing. + * + * @param translator contains schema versions configuration + * @param edgeIngestor provides edge rules + * @param edgePropsConfiguration edge property validation configuration + */ + @Autowired + public OxmEdgeRulesLoader(Translator translator, EdgeIngestor edgeIngestor, + EdgePropsConfiguration edgePropsConfiguration) { + OxmEdgeRulesLoader.translator = translator; + OxmEdgeRulesLoader.edgeIngestor = edgeIngestor; + OxmEdgeRulesLoader.edgePropsConfiguration = edgePropsConfiguration; + } + + /** + * Finds all DB Edge Rules and Edge Properties files for all OXM models. + * + * @throws SchemaProviderException + * @throws SchemaProviderException + */ + public static synchronized void loadModels() throws SchemaProviderException { + Map<String, File> propFiles = edgePropertyFiles(edgePropsConfiguration); + + if (logger.isDebugEnabled()) { + logger.debug("Loading DB Edge Rules"); + } + + for (String version : OxmSchemaLoader.getLoadedOXMVersions()) { + try { + SchemaVersion schemaVersion = translator.getSchemaVersions().getVersions().stream() + .filter(s -> s.toString().equalsIgnoreCase(version)).findAny().orElse(null); + loadModel(schemaVersion, edgeIngestor, propFiles); + } catch (IOException | EdgeRuleNotFoundException e) { + throw new SchemaProviderException(e.getMessage(), e); + } + } + } + + /** + * Loads DB Edge Rules and Edge Properties for a given version. + * + * @throws SchemaProviderException + */ + + public static synchronized void loadModels(String v) throws SchemaProviderException { + Map<String, File> propFiles = edgePropertyFiles(edgePropsConfiguration); + + if (logger.isDebugEnabled()) { + logger.debug("Loading DB Edge Rules "); + } + + try { + SchemaVersion schemaVersion = translator.getSchemaVersions().getVersions().stream() + .filter(s -> s.toString().equalsIgnoreCase(v)).findAny().orElse(null); + + loadModel(schemaVersion, edgeIngestor, propFiles); + } catch (IOException | EdgeRuleNotFoundException e) { + throw new SchemaProviderException(e.getMessage()); + } + } + + /** + * Retrieves the DB Edge Rule relationship schema for a given version. + * + * @param version - The OXM version that we want the DB Edge Rule for. + * @return - A RelationshipSchema of the DB Edge Rule for the OXM version. + * @throws SchemaProviderException + */ + public static RelationshipSchema getSchemaForVersion(String version) throws SchemaProviderException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } else if (!versionContextMap.containsKey(version)) { + logger.error(SchemaProviderMsgs.SCHEMA_LOAD_ERROR, "Error loading DB Edge Rules for: " + version); + throw new SchemaProviderException("Error loading DB Edge Rules for: " + version); + } + + return versionContextMap.get(version); + } + + /** + * Retrieves the DB Edge Rule relationship schema for all loaded OXM versions. + * + * @return - A Map of the OXM version and it's corresponding RelationshipSchema of the DB Edge Rule. + * @throws SchemaProviderException + */ + public static Map<String, RelationshipSchema> getSchemas() throws SchemaProviderException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } + return versionContextMap; + } + + /** + * Returns the latest available DB Edge Rule version. + * + * @return - A Map of the OXM version and it's corresponding RelationshipSchema of the DB Edge Rule. + * @throws SchemaProviderException + */ + public static String getLatestSchemaVersion() throws SchemaProviderException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } + + // If there are still no models available, then there's not much we can do... + if (versionContextMap.isEmpty()) { + logger.error(SchemaProviderMsgs.SCHEMA_LOAD_ERROR, "No available DB Edge Rules to get latest version for."); + throw new SchemaProviderException("No available DB Edge Rules to get latest version for."); + } + + // Iterate over the available model versions to determine which is the most + // recent. + Integer latestVersion = null; + String latestVersionStr = null; + for (String versionKey : versionContextMap.keySet()) { + + Matcher matcher = versionPattern.matcher(versionKey); + if (matcher.find()) { + + int currentVersion = Integer.parseInt(matcher.group(1)); + + if ((latestVersion == null) || (currentVersion > latestVersion)) { + latestVersion = currentVersion; + latestVersionStr = versionKey; + } + } + } + + return latestVersionStr; + } + + /** + * Reset the loaded DB Edge Rule schemas + * + */ + public static void resetSchemaVersionContext() { + versionContextMap = new ConcurrentHashMap<>(); + } + + private static synchronized void loadModel(SchemaVersion version, EdgeIngestor edgeIngestor, + Map<String, File> props) throws IOException, SchemaProviderException, EdgeRuleNotFoundException { + + Multimap<String, EdgeRule> edges = edgeIngestor.getAllRules(version); + String edgeProps; + if (props.get(version.toString().toLowerCase()) != null) { + edgeProps = IOUtils.toString(new FileInputStream(props.get(version.toString().toLowerCase())), "UTF-8"); + } else { + throw new FileNotFoundException("The Edge Properties file for OXM version " + version + "was not found."); + } + if (edges != null) { + RelationshipSchema rs = new RelationshipSchema(edges, edgeProps); + versionContextMap.put(version.toString().toLowerCase(), rs); + logger.info(SchemaProviderMsgs.LOADED_DB_RULE_FILE, version.toString()); + } + } + + private static Map<String, File> edgePropertyFiles(EdgePropsConfiguration edgePropsConfiguration) + throws SchemaProviderException { + Map<String, File> propsFiles = Arrays + .stream(new File(edgePropsConfiguration.getEdgePropsDir()) + .listFiles((d, name) -> propsFilePattern.matcher(name).matches())) + .collect(Collectors.toMap(new Function<File, String>() { + @Override + public String apply(File f) { + Matcher m1 = propsVersionPattern.matcher(f.getName()); + m1.find(); + return m1.group(0); + } + }, f -> f)); + return propsFiles; + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/OxmSchemaLoader.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/OxmSchemaLoader.java new file mode 100644 index 00000000..b3708b12 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/OxmSchemaLoader.java @@ -0,0 +1,236 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.oxm; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.persistence.dynamic.DynamicType; +import org.eclipse.persistence.internal.oxm.mappings.Descriptor; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.nodes.NodeIngestor; +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.SchemaProviderMsgs; +import org.onap.aai.schemaif.definitions.VertexSchema; +import org.onap.aai.setup.SchemaVersion; +import org.onap.aai.setup.Translator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * This class contains all of the logic for importing OXM model schemas from the available OXM + * schema files. + */ +@Component +public class OxmSchemaLoader { + + private static Translator translator; + private static NodeIngestor nodeIngestor; + + private static Map<String, DynamicJAXBContext> versionContextMap = new ConcurrentHashMap<>(); + private static Map<String, HashMap<String, DynamicType>> xmlElementLookup = new ConcurrentHashMap<>(); + private static Map<String, HashMap<String, VertexSchema>> vertexLookup = new ConcurrentHashMap<>(); + + final static Pattern versionPattern = Pattern.compile("(?i)v(\\d*)"); + + private static org.onap.aai.cl.api.Logger logger = + LoggerFactory.getInstance().getLogger(OxmSchemaLoader.class.getName()); + + private OxmSchemaLoader() {} + + /** + * This constructor presents an awkward marrying of Spring bean creation and static method use. This + * is technical debt that will need fixing. + * + * @param translator contains schema versions configuration + * @param nodeIngestor provides DynamicJAXBContext for the OXM version + */ + @Autowired + public OxmSchemaLoader(Translator translator, NodeIngestor nodeIngestor) { + OxmSchemaLoader.translator = translator; + OxmSchemaLoader.nodeIngestor = nodeIngestor; + } + + /** + * Finds all OXM model files + * + * @throws SchemaProviderException + * @throws IOException + * + */ + public synchronized static void loadModels() throws SchemaProviderException { + if (logger.isDebugEnabled()) { + logger.debug("Loading OXM Models"); + } + + for (SchemaVersion oxmVersion : translator.getSchemaVersions().getVersions()) { + DynamicJAXBContext jaxbContext = nodeIngestor.getContextForVersion(oxmVersion); + if (jaxbContext != null) { + loadModel(oxmVersion.toString(), jaxbContext); + } + } + } + + private synchronized static void loadModel(String oxmVersion, DynamicJAXBContext jaxbContext) { + versionContextMap.put(oxmVersion, jaxbContext); + loadXmlLookupMap(oxmVersion, jaxbContext); + loadVertexLookupMap(oxmVersion, jaxbContext); + logger.info(SchemaProviderMsgs.LOADED_SCHEMA_FILE, oxmVersion); + } + + /** + * Retrieves the JAXB context for the specified OXM model version. + * + * @param version - The OXM version that we want the JAXB context for. + * + * @return - A JAXB context derived from the OXM model schema. + * + * @throws SchemaProviderException + */ + public static DynamicJAXBContext getContextForVersion(String version) throws SchemaProviderException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } else if (!versionContextMap.containsKey(version)) { + throw new SchemaProviderException("Error loading oxm model: " + version); + } + + return versionContextMap.get(version); + } + + public static String getLatestVersion() throws SchemaProviderException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } + + // If there are still no models available, then there's not much we can do... + if (versionContextMap.isEmpty()) { + throw new SchemaProviderException("No available OXM schemas to get latest version for."); + } + + // Iterate over the available model versions to determine which is the most + // recent. + Integer latestVersion = null; + String latestVersionStr = null; + for (String versionKey : versionContextMap.keySet()) { + + Matcher matcher = versionPattern.matcher(versionKey); + if (matcher.find()) { + + int currentVersion = Integer.valueOf(matcher.group(1)); + + if ((latestVersion == null) || (currentVersion > latestVersion)) { + latestVersion = currentVersion; + latestVersionStr = versionKey; + } + } + } + + return latestVersionStr; + } + + private static void loadXmlLookupMap(String version, DynamicJAXBContext jaxbContext) { + + @SuppressWarnings("rawtypes") + List<Descriptor> descriptorsList = jaxbContext.getXMLContext().getDescriptors(); + HashMap<String, DynamicType> types = new HashMap<String, DynamicType>(); + + for (@SuppressWarnings("rawtypes") + Descriptor desc : descriptorsList) { + + DynamicType entity = jaxbContext.getDynamicType(desc.getAlias()); + String entityName = desc.getDefaultRootElement(); + types.put(entityName, entity); + } + xmlElementLookup.put(version, types); + } + + private static void loadVertexLookupMap(String version, DynamicJAXBContext jaxbContext) { + + @SuppressWarnings("rawtypes") + List<Descriptor> descriptorsList = jaxbContext.getXMLContext().getDescriptors(); + HashMap<String, VertexSchema> vertexMap = new HashMap<String, VertexSchema>(); + + for (@SuppressWarnings("rawtypes") + Descriptor desc : descriptorsList) { + try { + FromOxmVertexSchema vs = new FromOxmVertexSchema(); + vs.fromOxm(desc.getDefaultRootElement(), jaxbContext, getXmlLookupMap(version)); + vertexMap.put(vs.getName(), vs); + } catch (SchemaProviderException e) { + continue; + } + } + vertexLookup.put(version, vertexMap); + } + + /** + * Retrieves the list of all Loaded OXM versions. + * + * @return - A List of Strings of all loaded OXM versions. + * + * @throws SpikeException + */ + public static List<String> getLoadedOXMVersions() throws SchemaProviderException { + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } + // If there are still no models available, then there's not much we can do... + if (versionContextMap.isEmpty()) { + logger.error(SchemaProviderMsgs.SCHEMA_LOAD_ERROR, "No available OXM schemas to get versions for."); + throw new SchemaProviderException("No available OXM schemas to get latest version for."); + } + List<String> versions = new ArrayList<String>(); + for (String versionKey : versionContextMap.keySet()) { + Matcher matcher = versionPattern.matcher(versionKey); + if (matcher.find()) { + versions.add("V" + matcher.group(1)); + } + } + return versions; + } + + public static HashMap<String, DynamicType> getXmlLookupMap(String version) { + return xmlElementLookup.get(version); + } + + public static HashMap<String, VertexSchema> getVertexLookupForVersion(String version) throws SchemaProviderException { + // If we haven't already loaded in the available OXM models, then do so now. + if (vertexLookup == null || vertexLookup.isEmpty()) { + loadModels(); + } else if (!vertexLookup.containsKey(version)) { + throw new SchemaProviderException("Error loading oxm model: " + version); + } + return vertexLookup.get(version); + } + +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/OxmSchemaProvider.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/OxmSchemaProvider.java new file mode 100644 index 00000000..0ad8bf45 --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/OxmSchemaProvider.java @@ -0,0 +1,117 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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.aai.schemaif.oxm; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import org.onap.aai.edges.EdgeRule; +import org.onap.aai.schemaif.SchemaProvider; +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.definitions.EdgeSchema; +import org.onap.aai.schemaif.definitions.VertexSchema; + + +public class OxmSchemaProvider implements SchemaProvider { + + @Override + public void loadSchema() throws SchemaProviderException { + OxmEdgeRulesLoader.loadModels(); + OxmSchemaLoader.loadModels(); + } + + @Override + public String getLatestSchemaVersion() throws SchemaProviderException { + return OxmSchemaLoader.getLatestVersion(); + } + + @Override + public VertexSchema getVertexSchema(String vertexName, String schemaVersion) throws SchemaProviderException { + DynamicJAXBContext jaxbContext = OxmSchemaLoader.getContextForVersion(schemaVersion); + FromOxmVertexSchema vs = new FromOxmVertexSchema(); + + try { + vs.fromOxm(vertexName, jaxbContext, OxmSchemaLoader.getXmlLookupMap(schemaVersion)); + } + catch (SchemaProviderException ex) { + // Node doesn't exist in schema. Return null. + return null; + } + + return vs; + } + + @Override + public EdgeSchema getEdgeSchema(String edgeType, String sourceVertex, String targetVertex, String version) + throws SchemaProviderException { + RelationshipSchema relSchema = OxmEdgeRulesLoader.getSchemaForVersion(version); + String key = sourceVertex + ":" + targetVertex + ":" + edgeType; + + EdgeRule edgeRule = relSchema.lookupEdgeRule(key); + if (edgeRule == null) { + return null; + } + + FromOxmEdgeSchema es = new FromOxmEdgeSchema(); + es.fromEdgeRule(edgeRule); + + return es; + } + + @Override + public Set<EdgeSchema> getAdjacentEdgeSchema(String vertexType, String version) throws SchemaProviderException { + RelationshipSchema relSchema = OxmEdgeRulesLoader.getSchemaForVersion(version); + Set<EdgeSchema> edges = new HashSet<EdgeSchema>(); + List<EdgeRule> rules = relSchema.lookupAdjacentEdges(vertexType); + + for (EdgeRule rule : rules) { + FromOxmEdgeSchema es = new FromOxmEdgeSchema(); + es.fromEdgeRule(rule); + edges.add(es); + } + + return edges; + } + + @Override + public Set<EdgeSchema> getEdgeSchemaForSourceTarget(String sourceType, String targetType, String version) throws SchemaProviderException { + RelationshipSchema relSchema = OxmEdgeRulesLoader.getSchemaForVersion(version); + Set<EdgeSchema> edges = new HashSet<EdgeSchema>(); + Set<String> relTypes = relSchema.getValidRelationTypes(sourceType, targetType); + + for (String type : relTypes) { + EdgeSchema edgeSchema = getEdgeSchema(type, sourceType, targetType, version); + if (edgeSchema != null) { + edges.add(edgeSchema); + } + } + + return edges; + } + + @Override + public Map<String, VertexSchema> getVertexMap(String schemaVersion) throws SchemaProviderException { + return OxmSchemaLoader.getVertexLookupForVersion(schemaVersion); + } +} diff --git a/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/RelationshipSchema.java b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/RelationshipSchema.java new file mode 100644 index 00000000..fa4fe45d --- /dev/null +++ b/aai-schema-abstraction/src/main/java/org/onap/aai/schemaif/oxm/RelationshipSchema.java @@ -0,0 +1,189 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2019 AT&T Intellectual Property. All rights reserved. + * Copyright © 2019 Amdocs + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.schemaif.oxm; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.codehaus.jackson.map.ObjectMapper; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.edges.EdgeRule; +import org.onap.aai.schemaif.SchemaProviderException; +import org.onap.aai.schemaif.SchemaProviderMsgs; + +import com.google.common.collect.Multimap; + + +public class RelationshipSchema { + + + public static final String SCHEMA_SOURCE_NODE_TYPE = "from"; + public static final String SCHEMA_TARGET_NODE_TYPE = "to"; + public static final String SCHEMA_RELATIONSHIP_TYPE = "label"; + public static final String SCHEMA_RULES_ARRAY = "rules"; + + private static org.onap.aai.cl.api.Logger logger = + LoggerFactory.getInstance().getLogger(RelationshipSchema.class.getName()); + + private Map<String, Map<String, Class<?>>> relations = new HashMap<>(); + /** + * Hashmap of valid relationship types along with properties. + */ + private Map<String, Map<String, Class<?>>> relationTypes = new HashMap<>(); + private Map<String, EdgeRule> relationshipRules = new HashMap<>(); + + // A map storing the list of valid edge types for a source/target pair + private Map<String, Set<String>> edgeTypesForNodePair = new HashMap<>(); + + + public RelationshipSchema(Multimap<String, EdgeRule> rules, String props) throws SchemaProviderException, IOException { + HashMap<String, String> properties = new ObjectMapper().readValue(props, HashMap.class); + + // hold the true values of the edge rules by key + for (EdgeRule rule : rules.values()) { + String nodePairKey = buildNodePairKey(rule.getFrom(), rule.getTo()); + if (edgeTypesForNodePair.get(nodePairKey) == null) { + Set<String> typeSet = new HashSet<String>(); + typeSet.add(rule.getLabel()); + edgeTypesForNodePair.put(nodePairKey, typeSet); + } + else { + edgeTypesForNodePair.get(nodePairKey).add(rule.getLabel()); + } + + String key = buildRelation(rule.getFrom(), rule.getTo(), rule.getLabel()); + relationshipRules.put(key, rule); + } + + Map<String, Class<?>> edgeProps = + properties.entrySet().stream().collect(Collectors.toMap(p -> p.getKey(), p -> { + try { + return resolveClass(p.getValue()); + } catch (SchemaProviderException | ClassNotFoundException e) { + logger.error(SchemaProviderMsgs.SCHEMA_LOAD_ERROR, "Error in RelationshipSchema: " + e); + } + return null; + })); + + rules.entries().forEach((kv) -> { + relationTypes.put(kv.getValue().getLabel(), edgeProps); + relations.put(buildRelation(kv.getValue().getFrom(), kv.getValue().getTo(), kv.getValue().getLabel()), + edgeProps); + }); + } + + public EdgeRule lookupEdgeRule(String key) throws SchemaProviderException { + return relationshipRules.get(key); + } + + public List<EdgeRule> lookupAdjacentEdges(String vertex) throws SchemaProviderException { + List<EdgeRule> edges = new ArrayList<EdgeRule>(); + for (EdgeRule rule : relationshipRules.values()) { + if (rule.getFrom().equals(vertex) || rule.getTo().equals(vertex)) { + edges.add(rule); + } + } + + return edges; + } + + public RelationshipSchema(List<String> jsonStrings) throws SchemaProviderException, IOException { + String edgeRules = jsonStrings.get(0); + String props = jsonStrings.get(1); + + HashMap<String, ArrayList<LinkedHashMap<String, String>>> rules = + new ObjectMapper().readValue(edgeRules, HashMap.class); + HashMap<String, String> properties = new ObjectMapper().readValue(props, HashMap.class); + Map<String, Class<?>> edgeProps = + properties.entrySet().stream().collect(Collectors.toMap(p -> p.getKey(), p -> { + try { + return resolveClass(p.getValue()); + } catch (SchemaProviderException | ClassNotFoundException e) { + logger.error(SchemaProviderMsgs.SCHEMA_LOAD_ERROR, "Error in RelationshipSchema: " + e); + } + return null; + })); + + rules.get(SCHEMA_RULES_ARRAY).forEach(l -> { + relationTypes.put(l.get(SCHEMA_RELATIONSHIP_TYPE), edgeProps); + relations.put(buildRelation(l.get(SCHEMA_SOURCE_NODE_TYPE), l.get(SCHEMA_TARGET_NODE_TYPE), + l.get(SCHEMA_RELATIONSHIP_TYPE)), edgeProps); + }); + } + + + + public Map<String, Class<?>> lookupRelation(String key) { + return this.relations.get(key); + } + + public Map<String, Class<?>> lookupRelationType(String type) { + return this.relationTypes.get(type); + } + + public boolean isValidType(String type) { + return relationTypes.containsKey(type); + } + + + private String buildRelation(String source, String target, String relation) { + return source + ":" + target + ":" + relation; + } + + public Set<String> getValidRelationTypes(String source, String target) { + Set<String> typeList = edgeTypesForNodePair.get(buildNodePairKey(source, target)); + + if (typeList == null) { + return new HashSet<String>(); + } + + return typeList; + } + + private String buildNodePairKey(String source, String target) { + return source + ":" + target; + } + + + private Class<?> resolveClass(String type) throws SchemaProviderException, ClassNotFoundException { + Class<?> clazz = Class.forName(type); + validateClassTypes(clazz); + return clazz; + } + + private void validateClassTypes(Class<?> clazz) throws SchemaProviderException { + if (!clazz.isAssignableFrom(Integer.class) && !clazz.isAssignableFrom(Double.class) + && !clazz.isAssignableFrom(Boolean.class) && !clazz.isAssignableFrom(String.class)) { + throw new SchemaProviderException("BAD_REQUEST"); + } + } +} + + diff --git a/aai-schema-abstraction/src/main/resources/logging/SchemaProviderMsgs.properties b/aai-schema-abstraction/src/main/resources/logging/SchemaProviderMsgs.properties new file mode 100644 index 00000000..0feb2acd --- /dev/null +++ b/aai-schema-abstraction/src/main/resources/logging/SchemaProviderMsgs.properties @@ -0,0 +1,16 @@ + +## Error Logs +SCHEMA_LOAD_ERROR=\ + PVD0500E|\ + Unable to load schema: {0} + +## Info Logs +LOADED_SCHEMA_FILE=\ + PVD0001I|\ + Successfully loaded schema: {0} + +LOADED_DB_RULE_FILE=\ + PVD0002I|\ + Successfully loaded DB Edge Rule and Edge Properties for: {0} + + |