From 59b90519eda3b95b0cfc49b6349a591c7d0c78e2 Mon Sep 17 00:00:00 2001 From: liamfallon Date: Mon, 7 Feb 2022 17:56:44 +0000 Subject: Remove JAXB and XML, use GSON for JSON This review converst apex-pdp to use GSON for JSON handling. In order to preserve backward compatibility with the JAXB format of JSON, custom handling of maps was required. Therefore, the policy-common StandardCoder could not be used. There are a lot of small changes, removing annotations from concepts and tweaking of test data. However, this cleans up the code base so it is worth doing. Issue-ID: POLICY-1820 Change-Id: I213fa64f6d7f3f1df8d10f111d9fbedbe80f9fe0 Signed-off-by: liamfallon --- .../model/basicmodel/concepts/AxArtifactKey.java | 14 -- .../apex/model/basicmodel/concepts/AxConcept.java | 12 +- .../apex/model/basicmodel/concepts/AxKeyInfo.java | 17 +- .../basicmodel/concepts/AxKeyInformation.java | 37 +--- .../apex/model/basicmodel/concepts/AxModel.java | 19 -- .../model/basicmodel/concepts/AxReferenceKey.java | 134 +++++-------- .../model/basicmodel/concepts/package-info.java | 9 +- .../handling/ApexModelCustomGsonMapAdapter.java | 118 +++++++++++ .../ApexModelCustomGsonRefereceKeyAdapter.java | 50 +++++ .../basicmodel/handling/ApexModelFileWriter.java | 58 +----- .../model/basicmodel/handling/ApexModelReader.java | 157 +++------------ .../model/basicmodel/handling/ApexModelSaver.java | 21 +- .../basicmodel/handling/ApexModelStringWriter.java | 71 ++----- .../model/basicmodel/handling/ApexModelWriter.java | 216 ++++----------------- .../basicmodel/handling/ApexSchemaGenerator.java | 161 --------------- .../basicmodel/handling/KeyInfoMarshalFilter.java | 104 ---------- .../model/basicmodel/handling/package-info.java | 17 +- .../policy/apex/model/basicmodel/package-info.java | 4 +- .../apex/model/basicmodel/test/TestApexModel.java | 54 +----- .../basicmodel/xml/AxReferenceKeyAdapter.java | 58 ------ .../apex/model/basicmodel/xml/package-info.java | 34 ---- 21 files changed, 337 insertions(+), 1028 deletions(-) create mode 100644 model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelCustomGsonMapAdapter.java create mode 100644 model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelCustomGsonRefereceKeyAdapter.java delete mode 100644 model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexSchemaGenerator.java delete mode 100644 model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/KeyInfoMarshalFilter.java delete mode 100644 model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/xml/AxReferenceKeyAdapter.java delete mode 100644 model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/xml/package-info.java (limited to 'model/basic-model/src/main/java/org') diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxArtifactKey.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxArtifactKey.java index f5d421956..1efe83db8 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxArtifactKey.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxArtifactKey.java @@ -23,11 +23,6 @@ package org.onap.policy.apex.model.basicmodel.concepts; import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult; import org.onap.policy.common.utils.validation.Assertions; @@ -39,22 +34,13 @@ import org.onap.policy.common.utils.validation.Assertions; *

Key validation checks that the name and version fields match the NAME_REGEXP and VERSION_REGEXP * regular expressions respectively. */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlRootElement(name = "apexArtifactKey", namespace = "http://www.onap.org/policy/apex-pdp") - -@XmlType(name = "AxArtifactKey", namespace = "http://www.onap.org/policy/apex-pdp", propOrder = - { "name", "version" }) - public class AxArtifactKey extends AxKey { private static final long serialVersionUID = 8932717618579392561L; private static final String NAME_TOKEN = "name"; private static final String VERSION_TOKEN = "version"; - @XmlElement(required = true) private String name; - - @XmlElement(required = true) private String version; /** diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxConcept.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxConcept.java index 0e2c6bef2..37fe30b33 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxConcept.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxConcept.java @@ -1,7 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2019,2022 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,6 @@ package org.onap.policy.apex.model.basicmodel.concepts; import java.io.Serializable; import java.util.List; -import javax.xml.bind.annotation.XmlType; import org.onap.policy.common.utils.validation.Assertions; /** @@ -33,9 +32,6 @@ import org.onap.policy.common.utils.validation.Assertions; * * @author Liam Fallon (liam.fallon@ericsson.com) */ - -@XmlType(name = "AxConcept", namespace = "http://www.onap.org/policy/apex-pdp") - public abstract class AxConcept implements Serializable, Comparable { private static final long serialVersionUID = -7434939557282697490L; @@ -85,6 +81,12 @@ public abstract class AxConcept implements Serializable, Comparable { */ public abstract void clean(); + /** + * Builds references used by a concept. + */ + public void buildReferences() { + } + /** * {@inheritDoc}. */ diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxKeyInfo.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxKeyInfo.java index 9b96d3398..bd3b18ec9 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxKeyInfo.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxKeyInfo.java @@ -22,14 +22,10 @@ package org.onap.policy.apex.model.basicmodel.concepts; +import com.google.gson.annotations.SerializedName; import java.util.List; import java.util.Random; import java.util.UUID; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; import org.apache.commons.lang3.StringUtils; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult; import org.onap.policy.common.utils.validation.Assertions; @@ -41,16 +37,9 @@ import org.onap.policy.common.utils.validation.Assertions; *

Validation checks that all fields are defined and that the key is valid. It also observes that descriptions are * blank and warns if the UUID is a zero UUID. */ - -@XmlAccessorType(XmlAccessType.FIELD) -@XmlRootElement(name = "apexKeyInfo", namespace = "http://www.onap.org/policy/apex-pdp") -@XmlType(name = "AxKeyInfo", namespace = "http://www.onap.org/policy/apex-pdp", - propOrder = { "key", "uuid", "description" }) - public class AxKeyInfo extends AxConcept { private static final long serialVersionUID = -4023935924068914308L; - private static final int MAX_DESCRIPTION_LENGTH_8192 = 8192; private static final int UUID_BYTE_LENGTH_16 = 16; /* @@ -58,13 +47,11 @@ public class AxKeyInfo extends AxConcept { */ private static final Random sharedRandom = new Random(); // NOSONAR - @XmlElement(name = "key", required = true) private AxArtifactKey key; - @XmlElement(name = "UUID", required = true) + @SerializedName("UUID") private UUID uuid; - @XmlElement(required = true) private String description; /** diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxKeyInformation.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxKeyInformation.java index d1cc99a22..439b2960f 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxKeyInformation.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/concepts/AxKeyInformation.java @@ -30,11 +30,6 @@ import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.UUID; -import javax.xml.bind.Unmarshaller; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult; import org.onap.policy.common.utils.validation.Assertions; @@ -48,16 +43,10 @@ import org.onap.policy.common.utils.validation.Assertions; * the map is defined, that the key in each map entry matches the key if each entry value, and that no duplicate UUIDs * exist. Each key information entry is then validated individually. */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "AxKeyInformation", namespace = "http://www.onap.org/policy/apex-pdp", - propOrder = { "key", "keyInfoMap" }) - public class AxKeyInformation extends AxConcept implements AxConceptGetter { private static final long serialVersionUID = -2746380769017043888L; - @XmlElement(name = "key", required = true) private AxArtifactKey key; - private Map keyInfoMap; /** @@ -101,22 +90,6 @@ public class AxKeyInformation extends AxConcept implements AxConceptGetter navigablekeyInfoMap = new TreeMap<>(); - navigablekeyInfoMap.putAll(keyInfoMap); - keyInfoMap = navigablekeyInfoMap; - } - /** * This method generates default key information for all keys found in the concept passed in as a parameter that do * not already have key information. @@ -159,6 +132,14 @@ public class AxKeyInformation extends AxConcept implements AxConceptGetter keyInfo.buildReferences()); + } + /** * Sets the key of this concept. * @@ -218,7 +199,7 @@ public class AxKeyInformation extends AxConcept implements AxConceptGetter, JsonDeserializer { + private static final String MAP_ENTRY_KEY = "entry"; + + @SuppressWarnings("unchecked") + @Override + public Map deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + + if (!(jsonElement instanceof JsonObject)) { + throw new JsonParseException("could not parse JSON map, map is not a JsonObject"); + } + + JsonObject jsonObject = (JsonObject) jsonElement; + + if (jsonObject.size() != 1) { + throw new JsonParseException("could not parse JSON map, map must be in a JsonObject with a single member"); + } + + JsonArray mapEntryArray = (JsonArray) jsonObject.get(MAP_ENTRY_KEY); + if (mapEntryArray == null) { + throw new JsonParseException("could not parse JSON map, map \"entry\" in JsonObject not found"); + } + + return new TreeMap( + StreamSupport + .stream(mapEntryArray.spliterator(), true) + .map(element -> deserializeMapEntry(element, typeOfT, context)) + .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue())) + ); + } + + @Override + public JsonElement serialize(Map sourceMap, Type typeOfSrc, JsonSerializationContext context) { + + // A map is stored in a JsonArray + JsonArray mapEntryArray = new JsonArray(); + + for (Object mapEntryObject : sourceMap.entrySet()) { + Entry mapEntry = (Entry) mapEntryObject; + mapEntryArray.add(serializeMapEntry(mapEntry, typeOfSrc, context)); + } + + JsonObject returnObject = new JsonObject(); + returnObject.add(MAP_ENTRY_KEY, mapEntryArray); + + return returnObject; + } + + @SuppressWarnings("unchecked") + private static Entry deserializeMapEntry(JsonElement element, Type typeOfT, JsonDeserializationContext context) { + // Get the types of the map + ParameterizedType pt = (ParameterizedType) typeOfT; + + // Type of the key and value of the map + Type keyType = pt.getActualTypeArguments()[0]; + Type valueType = pt.getActualTypeArguments()[1]; + + // Deserialize the key and value + return new AbstractMap.SimpleEntry( + context.deserialize(element.getAsJsonObject().get("key"), keyType), + context.deserialize(element.getAsJsonObject().get("value"), valueType)); + } + + private static JsonElement serializeMapEntry(Entry sourceEntry, Type typeOfSrc, JsonSerializationContext context) { + // Get the types of the map + ParameterizedType pt = (ParameterizedType) typeOfSrc; + + // Type of the key and value of the map + Type keyType = pt.getActualTypeArguments()[0]; + Type valueType = pt.getActualTypeArguments()[1]; + + JsonObject entryObject = new JsonObject(); + entryObject.add("key", context.serialize(sourceEntry.getKey(), keyType)); + entryObject.add("value", context.serialize(sourceEntry.getValue(), valueType)); + + return entryObject; + } +} diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelCustomGsonRefereceKeyAdapter.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelCustomGsonRefereceKeyAdapter.java new file mode 100644 index 000000000..d731c8689 --- /dev/null +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelCustomGsonRefereceKeyAdapter.java @@ -0,0 +1,50 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.apex.model.basicmodel.handling; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import java.lang.reflect.Type; +import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; + +public class ApexModelCustomGsonRefereceKeyAdapter implements JsonDeserializer { + + @Override + public AxReferenceKey deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + + if (jsonElement instanceof JsonObject) { + return new AxReferenceKey( + jsonElement.getAsJsonObject().get("parentKeyName").getAsString(), + jsonElement.getAsJsonObject().get("parentKeyVersion").getAsString(), + jsonElement.getAsJsonObject().get("parentLocalName").getAsString(), + jsonElement.getAsJsonObject().get("localName").getAsString() + ); + } else { + AxReferenceKey returnKey = new AxReferenceKey(); + returnKey.setLocalName(jsonElement.getAsString()); + return returnKey; + } + } +} diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelFileWriter.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelFileWriter.java index 908ad31aa..54b5651cc 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelFileWriter.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelFileWriter.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021-2022 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,8 @@ package org.onap.policy.apex.model.basicmodel.handling; import java.io.File; import java.io.FileOutputStream; +import lombok.Getter; +import lombok.Setter; import org.onap.policy.apex.model.basicmodel.concepts.ApexException; import org.onap.policy.apex.model.basicmodel.concepts.AxModel; import org.slf4j.ext.XLogger; @@ -34,42 +36,21 @@ import org.slf4j.ext.XLoggerFactory; * @author Liam Fallon (liam.fallon@ericsson.com) * @param the type of Apex model to write to file, must be a sub class of {@link AxModel} */ +@Getter +@Setter public class ApexModelFileWriter { private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexModelFileWriter.class); // Should models being written to files be valid - private boolean validateFlag; + private boolean validate; /** * Constructor, set the validation flag. * - * @param validateFlag indicates if validation be performed prior to output + * @param validate indicates if validation be performed prior to output */ - public ApexModelFileWriter(final boolean validateFlag) { - this.validateFlag = validateFlag; - } - - /** - * Write a model to an XML file. - * - * @param model The model to write - * @param rootModelClass The concept class - * @param modelFileName The name of the file to write to - * @throws ApexException thrown on errors - */ - public void apexModelWriteXmlFile(final M model, final Class rootModelClass, final String modelFileName) - throws ApexException { - LOGGER.debug("running apexModelWriteXMLFile . . ."); - - final ApexModelWriter modelWriter = new ApexModelWriter<>(rootModelClass); - modelWriter.setValidateFlag(validateFlag); - modelWriter.getCDataFieldSet().add("description"); - modelWriter.getCDataFieldSet().add("logic"); - modelWriter.getCDataFieldSet().add("uiLogic"); - - writeModelFile(model, modelWriter, modelFileName); - - LOGGER.debug("ran apexModelWriteXMLFile"); + public ApexModelFileWriter(final boolean validate) { + this.validate = validate; } /** @@ -85,32 +66,13 @@ public class ApexModelFileWriter { LOGGER.debug("running apexModelWriteJSONFile . . ."); final ApexModelWriter modelWriter = new ApexModelWriter<>(rootModelClass); - modelWriter.setJsonOutput(true); - modelWriter.setValidateFlag(validateFlag); + modelWriter.setValidate(validate); writeModelFile(model, modelWriter, modelFileName); LOGGER.debug("ran apexModelWriteJSONFile"); } - /** - * Checks if the validation flag is set. - * - * @return true, the validation flag is set - */ - public boolean isValidateFlag() { - return validateFlag; - } - - /** - * Sets the validate flag. - * - * @param validateFlag the validate flag value - */ - public void setValidateFlag(final boolean validateFlag) { - this.validateFlag = validateFlag; - } - /** * Write a model to a file using a model writer. * diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelReader.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelReader.java index 7e136f6b3..a9bd2fe60 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelReader.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelReader.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2019-2021 Nordix Foundation. + * Modifications Copyright (C) 2019-2022 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,55 +22,47 @@ package org.onap.policy.apex.model.basicmodel.handling; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.StringReader; -import java.util.regex.Pattern; -import javax.xml.XMLConstants; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.SchemaFactory; -import org.eclipse.persistence.jaxb.JAXBContextFactory; -import org.eclipse.persistence.jaxb.MarshallerProperties; -import org.eclipse.persistence.oxm.MediaType; +import java.util.Map; +import lombok.Getter; +import lombok.Setter; import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; +import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; -import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.common.utils.resources.TextFileUtils; import org.onap.policy.common.utils.validation.Assertions; import org.slf4j.ext.XLogger; import org.slf4j.ext.XLoggerFactory; /** - * This class reads an Apex concept from an XML file into a Java Apex Concept {@link AxConcept}. + * This class reads an Apex concept from a file into a Java Apex Concept {@link AxConcept}. * * @author Liam Fallon (liam.fallon@ericsson.com) * @param the type of Apex concept to read, must be a sub class of {@link AxConcept} */ +@Getter +@Setter public class ApexModelReader { // Get a reference to the logger private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexModelReader.class); - // Regular expressions for checking input types - // (starts with - private static final String XML_INPUT_TYPE_REGEXP = "^\\s*<\\?xml.*>\\s*"; - // starts with some kind of bracket [ or ( - private static final String JSON_INPUT_TYPE_REGEXP = "^\\s*[\\(\\{\\[][\\s\\S]*[\\)\\}\\]]"; - // or {, then has something, then has - // and has a close bracket + // Use GSON to deserialize JSON + private static Gson gson = new GsonBuilder() + .registerTypeAdapter(AxReferenceKey.class, new ApexModelCustomGsonRefereceKeyAdapter()) + .registerTypeAdapter(Map.class, new ApexModelCustomGsonMapAdapter()) + .setPrettyPrinting() + .create(); //  The root class of the concept we are reading private final Class rootConceptClass; - // The unmarshaller for the Apex concepts - private Unmarshaller unmarshaller = null; - // All read concepts are validated after reading if this flag is set - private boolean validateFlag = true; + private boolean validate = true; /** * Constructor, initiates the reader with validation on. @@ -81,17 +73,6 @@ public class ApexModelReader { public ApexModelReader(final Class rootConceptClass) throws ApexModelException { // Save the root concept class this.rootConceptClass = rootConceptClass; - - try { - final var jaxbContext = JAXBContextFactory.createContext(new Class[] {rootConceptClass}, null); - - // Set up the unmarshaller to carry out validation - unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler()); - } catch (final JAXBException e) { - LOGGER.error("Unable to set JAXB context", e); - throw new ApexModelException("Unable to set JAXB context", e); - } } /** @@ -103,36 +84,11 @@ public class ApexModelReader { */ public ApexModelReader(final Class rootConceptClass, final boolean validate) throws ApexModelException { this(rootConceptClass); - this.validateFlag = validate; - } - - /** - * Set the schema to use for reading XML files. - * - * @param schemaFileName the schema file to use - * @throws ApexModelException if the schema cannot be set - */ - public void setSchema(final String schemaFileName) throws ApexModelException { - // Has a schema been set - if (schemaFileName != null) { - try { - // Set the concept schema - final var schemaUrl = ResourceUtils.getUrlResource(schemaFileName); - final var apexConceptSchema = - SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaUrl); - unmarshaller.setSchema(apexConceptSchema); - } catch (final Exception e) { - LOGGER.error("Unable to load schema ", e); - throw new ApexModelException("Unable to load schema", e); - } - } else { - // Clear the schema - unmarshaller.setSchema(null); - } + this.validate = validate; } /** - * This method checks the specified Apex concept XML file and reads it into an Apex concept. + * This method checks the specified Apex concept file and reads it into an Apex concept. * * @param apexConceptStream the apex concept stream * @return the Apex concept @@ -179,28 +135,23 @@ public class ApexModelReader { LOGGER.entry("reading Apex concept from string . . ."); - final var apexString = apexConceptString.trim(); - - // Set the type of input for this stream - setInputType(apexString); - - // The Apex Concept C apexConcept = null; - - // Use JAXB to read and verify the Apex concept XML file try { - // Load the configuration file - final var source = new StreamSource(new StringReader(apexString)); - final JAXBElement rootElement = unmarshaller.unmarshal(source, rootConceptClass); - apexConcept = rootElement.getValue(); - } catch (final JAXBException e) { - throw new ApexModelException("Unable to unmarshal Apex concept ", e); + apexConcept = gson.fromJson(apexConceptString, rootConceptClass); + } catch (final Exception je) { + throw new ApexModelException("Unable to unmarshal Apex concept ", je); + } + + if (apexConcept == null) { + throw new ApexModelException("Unable to unmarshal Apex concept, unmarshaled model is null "); } LOGGER.debug("reading of Apex concept {} completed"); + apexConcept.buildReferences(); + // Check if the concept should be validated - if (validateFlag) { + if (validate) { // Validate the configuration file final AxValidationResult validationResult = apexConcept.validate(new AxValidationResult()); if (validationResult.isValid()) { @@ -215,54 +166,4 @@ public class ApexModelReader { return apexConcept; } } - - /** - * Gets the value of the validation flag. - * - * @return the validation flag value - */ - public boolean getValidateFlag() { - return validateFlag; - } - - /** - * Sets the validation flag. - * - * @param validateFlag the validation flag value - */ - public void setValidateFlag(final boolean validateFlag) { - this.validateFlag = validateFlag; - } - - /** - * Set the type of input for the concept reader. - * - * @param apexConceptString The stream with - * @throws ApexModelException on errors setting input type - */ - private void setInputType(final String apexConceptString) throws ApexModelException { - // Check the input type - if (Pattern.compile(JSON_INPUT_TYPE_REGEXP).matcher(apexConceptString).find()) { - // is json - try { - unmarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON); - unmarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true); - } catch (final Exception e) { - LOGGER.warn("JAXB error setting marshaller for JSON Input", e); - throw new ApexModelException("JAXB error setting unmarshaller for JSON input", e); - } - } else if (Pattern.compile(XML_INPUT_TYPE_REGEXP).matcher(apexConceptString).find()) { - // is xml - try { - unmarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_XML); - } catch (final Exception e) { - LOGGER.warn("JAXB error setting marshaller for XML Input", e); - throw new ApexModelException("JAXB error setting unmarshaller for XML input", e); - } - } else { - LOGGER.warn("format of input for Apex concept is neither JSON nor XML"); - throw new ApexModelException("format of input for Apex concept is neither JSON nor XML"); - } - } - } diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelSaver.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelSaver.java index dea32df49..79d69bdd5 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelSaver.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelSaver.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2019-2021 Nordix Foundation. + * Modifications Copyright (C) 2019-2022 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ import org.slf4j.ext.XLogger; import org.slf4j.ext.XLoggerFactory; /** - * This class is used to save Apex models to file in XML or JSON format. + * This class is used to save Apex models to file in JSON format. * * @author Liam Fallon (liam.fallon@ericsson.com) * @param the type of Apex model to save to file, must be a sub class of {@link AxModel} @@ -51,7 +51,7 @@ public class ApexModelSaver { * @param rootModelClass the class of the model, a sub class of {@link AxModel} * @param model the model to write, an instance of a sub class of {@link AxModel} * @param writePath the directory to which models will be written. The name of the written model will be the Model - * Name for its key with the suffix {@code .xml} or {@code .json}. + * Name for its key with the suffix {@code .json}. */ public ApexModelSaver(final Class rootModelClass, final M model, final String writePath) { Assertions.argumentNotNull(rootModelClass, "argument rootModelClass may not be null"); @@ -63,21 +63,6 @@ public class ApexModelSaver { this.writePath = writePath; } - /** - * Write an Apex model to a file in XML format. The model will be written to {@code } - * - * @throws ApexException on errors writing the Apex model - */ - public void apexModelWriteXml() throws ApexException { - LOGGER.debug("running apexModelWriteXML . . ."); - - // Write the file to disk - final var xmlFile = new File(writePath + File.separatorChar + model.getKey().getName() + ".xml"); - new ApexModelFileWriter(true).apexModelWriteXmlFile(model, rootModelClass, xmlFile.getPath()); - - LOGGER.debug("ran apexModelWriteXML"); - } - /** * Write an Apex model to a file in JSON format. The model will be written to {@code } * diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelStringWriter.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelStringWriter.java index de6a72ffd..a9df23afc 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelStringWriter.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelStringWriter.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2019-2021 Nordix Foundation. + * Modifications Copyright (C) 2019-2022 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,8 @@ package org.onap.policy.apex.model.basicmodel.handling; import java.io.ByteArrayOutputStream; +import lombok.Getter; +import lombok.Setter; import org.onap.policy.apex.model.basicmodel.concepts.ApexException; import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; import org.onap.policy.common.utils.validation.Assertions; @@ -34,19 +36,21 @@ import org.slf4j.ext.XLoggerFactory; * @author Liam Fallon (liam.fallon@ericsson.com) * @param the type of Apex concept to write to a string, must be a sub class of {@link AxConcept} */ +@Getter +@Setter public class ApexModelStringWriter { private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexModelStringWriter.class); // Should concepts being written to files be valid - private boolean validateFlag; + private boolean validate; /** * Constructor, set the validation flag. * - * @param validateFlag Should validation be performed prior to output + * @param validate Should validation be performed prior to output */ - public ApexModelStringWriter(final boolean validateFlag) { - this.validateFlag = validateFlag; + public ApexModelStringWriter(final boolean validate) { + this.validate = validate; } /** @@ -54,46 +58,14 @@ public class ApexModelStringWriter { * * @param concept The concept to write * @param rootConceptClass The concept class - * @param jsonFlag writes JSON if true, and a generic string if false * @return The string with the concept * @throws ApexException thrown on errors */ - public String writeString(final C concept, final Class rootConceptClass, final boolean jsonFlag) + public String writeString(final C concept, final Class rootConceptClass) throws ApexException { Assertions.argumentNotNull(concept, "concept may not be null"); - if (jsonFlag) { - return writeJsonString(concept, rootConceptClass); - } else { - return concept.toString(); - } - } - - /** - * Write a concept to an XML string. - * - * @param concept The concept to write - * @param rootConceptClass The concept class - * @return The string with the concept - * @throws ApexException thrown on errors - */ - public String writeXmlString(final C concept, final Class rootConceptClass) throws ApexException { - LOGGER.debug("running writeXMLString . . ."); - - final ApexModelWriter conceptWriter = new ApexModelWriter<>(rootConceptClass); - conceptWriter.setValidateFlag(validateFlag); - conceptWriter.getCDataFieldSet().add("description"); - conceptWriter.getCDataFieldSet().add("logic"); - conceptWriter.getCDataFieldSet().add("uiLogic"); - - try (var baOutputStream = new ByteArrayOutputStream()) { - conceptWriter.write(concept, baOutputStream); - return baOutputStream.toString(); - } catch (final Exception e) { - LOGGER.warn("error writing XML string", e); - throw new ApexException("error writing XML string", e); - } - + return writeJsonString(concept, rootConceptClass); } /** @@ -108,8 +80,7 @@ public class ApexModelStringWriter { LOGGER.debug("running writeJSONString . . ."); final ApexModelWriter conceptWriter = new ApexModelWriter<>(rootConceptClass); - conceptWriter.setJsonOutput(true); - conceptWriter.setValidateFlag(validateFlag); + conceptWriter.setValidate(validate); try (var baOutputStream = new ByteArrayOutputStream()) { conceptWriter.write(concept, baOutputStream); @@ -120,22 +91,4 @@ public class ApexModelStringWriter { } } - - /** - * Checks if is validate flag. - * - * @return true, if checks if is validate flag - */ - public boolean isValidateFlag() { - return validateFlag; - } - - /** - * Sets the validate flag. - * - * @param validateFlag the validate flag - */ - public void setValidateFlag(final boolean validateFlag) { - this.validateFlag = validateFlag; - } } diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelWriter.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelWriter.java index 9e43f76bd..349622697 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelWriter.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexModelWriter.java @@ -1,7 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2019-2021 Nordix Foundation. + * Modifications Copyright (C) 2019-2022 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,129 +21,67 @@ package org.onap.policy.apex.model.basicmodel.handling; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; -import java.util.Set; -import java.util.TreeSet; -import javax.xml.XMLConstants; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import org.eclipse.persistence.jaxb.JAXBContextFactory; -import org.eclipse.persistence.jaxb.MarshallerProperties; -import org.eclipse.persistence.oxm.MediaType; +import java.util.Map; +import lombok.Getter; +import lombok.Setter; import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; +import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; import org.onap.policy.common.utils.validation.Assertions; import org.slf4j.ext.XLogger; import org.slf4j.ext.XLoggerFactory; /** - * This class writes an Apex concept to an XML file or JSON file from a Java Apex Concept. + * This class writes an Apex concept to a file from a Java Apex Concept. * * @param the type of Apex concept to write, must be a sub class of {@link AxConcept} * @author John Keeney (john.keeney@ericsson.com) */ +@Getter +@Setter public class ApexModelWriter { private static final String CONCEPT_MAY_NOT_BE_NULL = "concept may not be null"; private static final String CONCEPT_WRITER_MAY_NOT_BE_NULL = "concept writer may not be null"; private static final String CONCEPT_STREAM_MAY_NOT_BE_NULL = "concept stream may not be null"; + // Use GSON to serialize JSON + private static Gson gson = new GsonBuilder() + .registerTypeAdapter(AxReferenceKey.class, new ApexModelCustomGsonRefereceKeyAdapter()) + .registerTypeAdapter(Map.class, new ApexModelCustomGsonMapAdapter()) + .setPrettyPrinting() + .create(); + // Get a reference to the logger private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexModelWriter.class); - // Writing as JSON or XML - private boolean jsonOutput = false; - - // The list of fields to output as CDATA - private final Set cdataFieldSet = new TreeSet<>(); - - // The Marshaller for the Apex concepts - private Marshaller marshaller = null; + //  The root class of the concept we are reading + private final Class rootConceptClass; // All written concepts are validated before writing if this flag is set - private boolean validateFlag = true; + private boolean validate = true; /** - * Constructor, initiates the writer. + * Constructor, initiates the writer with validation on. * * @param rootConceptClass the root concept class for concept reading - * @throws ApexModelException the apex concept writer exception + * @throws ApexModelException the apex concept reader exception */ public ApexModelWriter(final Class rootConceptClass) throws ApexModelException { - // Set up Eclipselink for XML and JSON output - System.setProperty("javax.xml.bind.context.factory", "org.eclipse.persistence.jaxb.JAXBContextFactory"); - - try { - final var jaxbContext = JAXBContextFactory.createContext(new Class[]{rootConceptClass}, null); - - // Set up the unmarshaller to carry out validation - marshaller = jaxbContext.createMarshaller(); - marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); - marshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler()); - } catch (final JAXBException e) { - throw new ApexModelException("JAXB marshaller creation exception", e); - } - } - - /** - * The set of fields to be output as CDATA. - * - * @return the set of fields - */ - public Set getCDataFieldSet() { - return cdataFieldSet; - } - - /** - * Return true if JSON output enabled, XML output if false. - * - * @return true for JSON output - */ - public boolean isJsonOutput() { - return jsonOutput; - } - - /** - * Set the value of JSON output, true for JSON output, false for XML output. - * - * @param jsonOutput true for JSON output - * @throws ApexModelException on errors setting output type - */ - public void setJsonOutput(final boolean jsonOutput) throws ApexModelException { - this.jsonOutput = jsonOutput; - - // Set up output specific parameters - if (this.jsonOutput) { - try { - marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON); - marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true); - } catch (final Exception e) { - throw new ApexModelException("JAXB error setting marshaller for JSON output", e); - } - } else { - try { - marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_XML); - } catch (final Exception e) { - throw new ApexModelException("JAXB error setting marshaller for XML output", e); - } - } + // Save the root concept class + this.rootConceptClass = rootConceptClass; } /** * This method validates the Apex concept then writes it into a stream. * - * @param concept the concept to write + * @param concept the concept to write * @param apexConceptStream the stream to write to * @throws ApexModelException on validation or writing exceptions */ @@ -157,7 +95,7 @@ public class ApexModelWriter { /** * This method validates the Apex concept then writes it into a writer. * - * @param concept the concept to write + * @param concept the concept to write * @param apexConceptWriter the writer to write to * @throws ApexModelException on validation or writing exceptions */ @@ -166,84 +104,23 @@ public class ApexModelWriter { Assertions.argumentNotNull(apexConceptWriter, CONCEPT_WRITER_MAY_NOT_BE_NULL); // Check if we should validate the concept - if (validateFlag) { + if (validate) { // Validate the concept first final AxValidationResult validationResult = concept.validate(new AxValidationResult()); if (!validationResult.isValid()) { String message = - "Apex concept xml (" + concept.getKey().getId() + ") validation failed: " + validationResult - .toString(); + "Apex concept (" + concept.getKey().getId() + ") validation failed: " + validationResult.toString(); throw new ApexModelException(message); } } - if (jsonOutput) { - writeJson(concept, apexConceptWriter); - } else { - writeXml(concept, apexConceptWriter); - } - } - - /** - * This method writes the Apex concept into a writer in XML format. - * - * @param concept the concept to write - * @param apexConceptWriter the writer to write to - * @throws ApexModelException on validation or writing exceptions - */ - private void writeXml(final C concept, final Writer apexConceptWriter) throws ApexModelException { - Assertions.argumentNotNull(concept, CONCEPT_MAY_NOT_BE_NULL); - - LOGGER.debug("writing Apex concept XML . . ."); - - try { - // Write the concept into a DOM document, then transform to add CDATA fields and pretty - // print, then write out the result - final var docBuilderFactory = DocumentBuilderFactory.newInstance(); - docBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); - docBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); - - docBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - final var document = docBuilderFactory.newDocumentBuilder().newDocument(); - - // Marshal the concept into the empty document. - marshaller.marshal(concept, document); - - final var domTransformer = getTransformer(); - - // Convert the cDataFieldSet into a space delimited string - domTransformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, - cdataFieldSet.toString().replaceAll("[\\[\\]\\,]", " ")); - domTransformer.transform(new DOMSource(document), new StreamResult(apexConceptWriter)); - } catch (JAXBException | TransformerException | ParserConfigurationException e) { - throw new ApexModelException("Unable to marshal Apex concept to XML", e); - } - LOGGER.debug("wrote Apex concept XML"); - } - - private Transformer getTransformer() throws TransformerConfigurationException { - // Transform the DOM to the output stream - final var transformerFactory = TransformerFactory.newInstance(); - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); - - final var domTransformer = transformerFactory.newTransformer(); - - // Pretty print - try { - domTransformer.setOutputProperty(OutputKeys.INDENT, "yes"); - // May fail if not using XALAN XSLT engine. But not in any way vital - domTransformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); - } catch (final Exception ignore) { - LOGGER.trace("Unable to set indent property", ignore); - } - return domTransformer; + writeJson(concept, apexConceptWriter); } /** * This method writes the Apex concept into a writer in JSON format. * - * @param concept the concept to write + * @param concept the concept to write * @param apexConceptWriter the writer to write to * @throws ApexModelException on validation or writing exceptions */ @@ -252,29 +129,20 @@ public class ApexModelWriter { LOGGER.debug("writing Apex concept JSON . . ."); + String modelJsonString = null; try { - marshaller.marshal(concept, apexConceptWriter); - } catch (final JAXBException e) { - throw new ApexModelException("Unable to marshal Apex concept to JSON", e); + modelJsonString = gson.toJson(concept, rootConceptClass); + } catch (Exception je) { + throw new ApexModelException("Unable to marshal Apex concept to JSON", je); } - LOGGER.debug("wrote Apex concept JSON"); - } - /** - * Gets the validation flag value. - * - * @return the validation flag value - */ - public boolean getValidateFlag() { - return validateFlag; - } + try { + apexConceptWriter.write(modelJsonString); + apexConceptWriter.close(); + } catch (IOException ioe) { + throw new ApexModelException("Unable to write Apex concept as JSON", ioe); + } - /** - * Sets the validation flag. - * - * @param validateFlag the validation flag value - */ - public void setValidateFlag(final boolean validateFlag) { - this.validateFlag = validateFlag; + LOGGER.debug("wrote Apex concept JSON"); } } diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexSchemaGenerator.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexSchemaGenerator.java deleted file mode 100644 index d5f34785b..000000000 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/ApexSchemaGenerator.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2020-2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.apex.model.basicmodel.handling; - -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; -import java.io.StringWriter; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.SchemaOutputResolver; -import javax.xml.transform.Result; -import javax.xml.transform.stream.StreamResult; -import org.slf4j.ext.XLogger; -import org.slf4j.ext.XLoggerFactory; - -/** - * This class generates the XML model schema from the given Apex concept classes. - * - * @author Liam Fallon (liam.fallon@ericsson.com) - */ -public class ApexSchemaGenerator { - // Get a reference to the logger - private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexSchemaGenerator.class); - - /** - * A Main method to allow schema generation from the command line or from maven or scripts. - * - * @param args the command line arguments, usage is {@code ApexSchemaGenerator apex-root-class [schema-file-name]} - */ - public static void main(final String[] args) { - PrintStream printStream = null; - - if (args.length == 1) { - printStream = System.out; - } else if (args.length == 2) { - final var schemaFile = new File(args[1]); - - try { - schemaFile.getParentFile().mkdirs(); - printStream = new PrintStream(schemaFile); - } catch (final Exception e) { - LOGGER.error("error on Apex schema output", e); - return; - } - } else { - LOGGER.error("usage: ApexSchemaGenerator apex-root-class [schema-file-name]"); - return; - } - - // Get the schema - final String schema = new ApexSchemaGenerator().generate(args[0]); - - // Output the schema - printStream.println(schema); - - printStream.close(); - } - - /** - * Generates the XML schema (XSD) for the Apex model described using JAXB annotations. - * - * @param rootClassName the name of the root class for schema generation - * @return The schema - */ - public String generate(final String rootClassName) { - JAXBContext jaxbContext; - try { - jaxbContext = JAXBContext.newInstance(Class.forName(rootClassName)); - } catch (final ClassNotFoundException e) { - LOGGER.error("could not create JAXB context, root class " + rootClassName + " not found", e); - return null; - } catch (final JAXBException e) { - LOGGER.error("could not create JAXB context", e); - return null; - } - - final var sor = new ApexSchemaOutputResolver(); - try { - jaxbContext.generateSchema(sor); - } catch (final IOException e) { - LOGGER.error("error generating the Apex schema (XSD) file", e); - return null; - } - - var schemaString = sor.getSchema(); - schemaString = fixForUnqualifiedBug(schemaString); - - return schemaString; - } - - /** - * There is a bug in schema generation that does not specify the elements from Java Maps as being unqualified. This - * method "hacks" those elements in the schema to fix this, the elements being {@code entry}, {@code key}, and - * {@code value} - * - * @param schemaString The schema in which elements should be fixed - * @return the string - */ - private String fixForUnqualifiedBug(final String schemaString) { - // Fix the "entry" element - var newSchemaString = schemaString.replace( - "", - ""); - - // Fix the "key" element - newSchemaString = newSchemaString.replace(" { - - private List filterList = new LinkedList<>(); - - /** - * Adds a key to the list to be filtered. - * - * @param key the key to add to the filter list - */ - public void addFilterKey(AxKey key) { - filterList.add(key); - } - - /** - * Remove a key from the list to be filtered. - * - * @param key the key to remove from the filter list - * @return true if the passed key was in the filter list and has been removed. - */ - public boolean removeFilterKey(AxKey key) { - return filterList.remove(key); - } - - /** - * Adds some keys to the list to be filtered. - * - * @param keys the keys to add to the filter list - */ - public void addFilterKeys(Collection keys) { - filterList.addAll(keys); - } - - /** - * Decide whether to unmarshall some keyinfos - Always. - * - * @param val the keyinfo - * @return the keyinfo - * @throws Exception if there is some problem unmarshalling - * @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(Object) - */ - @Override - public AxKeyInformation unmarshal(AxKeyInformation val) throws Exception { - return val; - } - - /** - * Select which keyinfo entries will be marshalled - i.e. those not in the filter list. - * - * @param val the keyinfo - * @return the keyinfo - * @throws Exception if there is some problem with the marshalling - * @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(Object) - */ - @Override - public AxKeyInformation marshal(AxKeyInformation val) throws Exception { - if (val == null || val.getKeyInfoMap() == null || val.getKeyInfoMap().isEmpty() || filterList.isEmpty()) { - return val; - } - //create a new keyinfo clone to avoid removing keyinfo entries from the original model - AxKeyInformation ret = new AxKeyInformation(val); - Map retmap = new TreeMap<>(ret.getKeyInfoMap()); - for (AxKey key : filterList) { - retmap.remove(key); - } - ret.setKeyInfoMap(retmap); - return ret; - } -} diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/package-info.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/package-info.java index 081cff540..3d6dab3b2 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/package-info.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/handling/package-info.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2022 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,20 +18,4 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ - -/** - * Contains a number of utility classes for handling APEX {@link org.onap.policy.apex.model.basicmodel.concepts.AxModel} - * models and {@link org.onap.policy.apex.model.basicmodel.concepts.AxConcept} concepts. Classes to read and write - * models to files, strings, and databases are included, as well as classes to generate XML schemas for models. - * - * @author Liam Fallon (liam.fallon@ericsson.com) - */ - -@XmlSchema(namespace = "http://www.onap.org/policy/apex-pdp", elementFormDefault = XmlNsForm.QUALIFIED, - xmlns = { @XmlNs(namespaceURI = "http://www.onap.org/policy/apex-pdp", prefix = "") }) - package org.onap.policy.apex.model.basicmodel.handling; - -import javax.xml.bind.annotation.XmlNs; -import javax.xml.bind.annotation.XmlNsForm; -import javax.xml.bind.annotation.XmlSchema; diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/package-info.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/package-info.java index e540646d9..8ad405e25 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/package-info.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/package-info.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2019,2022 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ * the model for APEX concepts anywhere in the system. * *

It also provides handling support to models, allowing them to be read and written to file and databases in JSON - * and XML format. + * format. * * @author Liam Fallon (liam.fallon@ericsson.com) */ diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/test/TestApexModel.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/test/TestApexModel.java index 5dbf69492..9dde47d05 100644 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/test/TestApexModel.java +++ b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/test/TestApexModel.java @@ -44,7 +44,7 @@ import org.slf4j.ext.XLoggerFactory; public class TestApexModel { private static final String MODEL_IS_INVALID = "model is invalid "; private static final String ERROR_PROCESSING_FILE = "error processing file "; - private static final String TEST_MODEL_UNEQUAL_STR = "test model does not equal model read from XML file "; + private static final String TEST_MODEL_UNEQUAL_STR = "test model does not equal model read from file "; private static final String TEMP_FILE_CREATE_ERR_STR = "error creating temporary file for Apex model"; private static final XLogger LOGGER = XLoggerFactory.getXLogger(TestApexModel.class); @@ -76,55 +76,6 @@ public class TestApexModel { return modelCreator.getModel(); } - /** - * Test write and read in XML format. - * - * @throws ApexException on write/read errors - */ - public final void testApexModelWriteReadXml() throws ApexException { - LOGGER.debug("running testApexModelWriteReadXML . . ."); - - final var model = modelCreator.getModel(); - - // Write the file to disk - File xmlFile; - - try { - xmlFile = File.createTempFile("ApexModel", ".xml"); - xmlFile.deleteOnExit(); - } catch (final Exception e) { - LOGGER.warn(TEMP_FILE_CREATE_ERR_STR, e); - throw new ApexException(TEMP_FILE_CREATE_ERR_STR, e); - } - new ApexModelFileWriter(true).apexModelWriteXmlFile(model, rootModelClass, xmlFile.getPath()); - - // Read the file from disk - final ApexModelReader modelReader = new ApexModelReader<>(rootModelClass); - - try { - final var apexModelUrl = ResourceUtils.getLocalFile(xmlFile.getAbsolutePath()); - final var fileModel = modelReader.read(apexModelUrl.openStream()); - checkModelEquality(model, fileModel, TEST_MODEL_UNEQUAL_STR + xmlFile.getAbsolutePath()); - } catch (final Exception e) { - LOGGER.warn(ERROR_PROCESSING_FILE + xmlFile.getAbsolutePath(), e); - throw new ApexException(ERROR_PROCESSING_FILE + xmlFile.getAbsolutePath(), e); - } - - final ApexModelWriter modelWriter = new ApexModelWriter<>(rootModelClass); - modelWriter.getCDataFieldSet().add("description"); - modelWriter.getCDataFieldSet().add("logic"); - modelWriter.getCDataFieldSet().add("uiLogic"); - - final var baOutputStream = new ByteArrayOutputStream(); - modelWriter.write(model, baOutputStream); - final var baInputStream = new ByteArrayInputStream(baOutputStream.toByteArray()); - final var byteArrayModel = modelReader.read(baInputStream); - - checkModelEquality(model, byteArrayModel, "test model does not equal XML marshalled and unmarshalled model"); - - LOGGER.debug("ran testApexModelWriteReadXML"); - } - /** * Test write and read in JSON format. * @@ -138,7 +89,7 @@ public class TestApexModel { // Write the file to disk File jsonFile; try { - jsonFile = File.createTempFile("ApexModel", ".xml"); + jsonFile = File.createTempFile("ApexModel", ".json"); jsonFile.deleteOnExit(); } catch (final Exception e) { LOGGER.warn(TEMP_FILE_CREATE_ERR_STR, e); @@ -159,7 +110,6 @@ public class TestApexModel { } final ApexModelWriter modelWriter = new ApexModelWriter<>(rootModelClass); - modelWriter.setJsonOutput(true); final var baOutputStream = new ByteArrayOutputStream(); modelWriter.write(model, baOutputStream); diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/xml/AxReferenceKeyAdapter.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/xml/AxReferenceKeyAdapter.java deleted file mode 100644 index 8515f5724..000000000 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/xml/AxReferenceKeyAdapter.java +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.apex.model.basicmodel.xml; - -import java.io.Serializable; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.adapters.XmlAdapter; -import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; - -/** - * This class manages marshaling and unmarshaling of Apex {@link AxReferenceKey} concepts using JAXB. The local name in - * reference keys must have specific handling. - */ -@XmlAccessorType(XmlAccessType.PROPERTY) -@XmlType(namespace = "http://www.onap.org/policy/apex-pdp") -public class AxReferenceKeyAdapter extends XmlAdapter implements Serializable { - - private static final long serialVersionUID = -3480405083900107029L; - - /** - * {@inheritDoc}. - */ - @Override - public final String marshal(final AxReferenceKey key) throws Exception { - return key.getLocalName(); - } - - /** - * {@inheritDoc}. - */ - @Override - public final AxReferenceKey unmarshal(final String key) throws Exception { - final var axReferenceKey = new AxReferenceKey(); - axReferenceKey.setLocalName(key); - return axReferenceKey; - } -} diff --git a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/xml/package-info.java b/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/xml/package-info.java deleted file mode 100644 index 290209d89..000000000 --- a/model/basic-model/src/main/java/org/onap/policy/apex/model/basicmodel/xml/package-info.java +++ /dev/null @@ -1,34 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -/** - * Contains utility classes for managing marshaling and unmarshaling of APEX models using JAXB. - * - * @author Liam Fallon (liam.fallon@ericsson.com) - */ - -@XmlSchema(namespace = "http://www.onap.org/policy/apex-pdp", elementFormDefault = XmlNsForm.QUALIFIED, - xmlns = { @XmlNs(namespaceURI = "http://www.onap.org/policy/apex-pdp", prefix = "") }) - -package org.onap.policy.apex.model.basicmodel.xml; - -import javax.xml.bind.annotation.XmlNs; -import javax.xml.bind.annotation.XmlNsForm; -import javax.xml.bind.annotation.XmlSchema; -- cgit 1.2.3-korg