diff options
Diffstat (limited to 'model/basic-model/src/main/java/org/onap/apex/model/basicmodel/handling/ApexModelReader.java')
-rw-r--r-- | model/basic-model/src/main/java/org/onap/apex/model/basicmodel/handling/ApexModelReader.java | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/model/basic-model/src/main/java/org/onap/apex/model/basicmodel/handling/ApexModelReader.java b/model/basic-model/src/main/java/org/onap/apex/model/basicmodel/handling/ApexModelReader.java new file mode 100644 index 000000000..84760f5db --- /dev/null +++ b/model/basic-model/src/main/java/org/onap/apex/model/basicmodel/handling/ApexModelReader.java @@ -0,0 +1,279 @@ +/* + * ============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========================================================= + */ + +package org.onap.apex.model.basicmodel.handling; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.net.URL; +import java.util.regex.Pattern; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +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.Schema; +import javax.xml.validation.SchemaFactory; + +import org.eclipse.persistence.jaxb.JAXBContextFactory; +import org.eclipse.persistence.jaxb.MarshallerProperties; +import org.eclipse.persistence.oxm.MediaType; +import org.onap.apex.model.basicmodel.concepts.AxConcept; +import org.onap.apex.model.basicmodel.concepts.AxValidationResult; +import org.onap.policy.apex.model.utilities.Assertions; +import org.onap.policy.apex.model.utilities.ResourceUtils; +import org.onap.policy.apex.model.utilities.TextFileUtils; +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}. + * + * @author Liam Fallon (liam.fallon@ericsson.com) + * @param <C> the type of Apex concept to read, must be a sub class of {@link AxConcept} + */ +public class ApexModelReader<C extends AxConcept> { + // Get a reference to the logger + private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexModelReader.class); + + // Regular expressions for checking input types + private static final String XML_INPUT_TYPE_REGEXP = "^\\s*<\\?xml.*>\\s*"; // (starts with <?xml...> + private static final String JSON_INPUT_TYPE_REGEXP = "^\\s*[\\(\\{\\[][\\s+\\S]*[\\)\\}\\]]"; // starts with some kind of bracket [ or ( + // or {, then has something, then has + // and has a close bracket + + // The root class of the concept we are reading + private final Class<C> 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; + + /** + * Constructor, initiates the reader with validation on. + * + * @param rootConceptClass the root concept class for concept reading + * @throws ApexModelException the apex concept reader exception + */ + public ApexModelReader(final Class<C> rootConceptClass) throws ApexModelException { + // Save the root concept class + this.rootConceptClass = rootConceptClass; + + try { + final JAXBContext 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); + } + } + + /** + * Constructor, initiates the reader. + * + * @param rootConceptClass the root concept class for concept reading + * @param validate whether to perform validation by default + * @throws ApexModelException the apex concept reader exception + */ + public ApexModelReader(final Class<C> 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 URL schemaURL = ResourceUtils.getURLResource(schemaFileName); + final Schema 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 method checks the specified Apex concept XML file and reads it into an Apex concept. + * + * @param apexConceptStream the apex concept stream + * @return the Apex concept + * @throws ApexModelException on reading exceptions + */ + public C read(final InputStream apexConceptStream) throws ApexModelException { + Assertions.argumentNotNull(apexConceptStream, "concept stream may not be null"); + + return read(new BufferedReader(new InputStreamReader(apexConceptStream))); + } + + /** + * This method reads the specified Apex reader into an Apex concept. + * + * @param apexConceptReader the apex concept reader + * @return the Apex concept + * @throws ApexModelException on reading exceptions + */ + public C read(final BufferedReader apexConceptReader) throws ApexModelException { + Assertions.argumentNotNull(apexConceptReader, "concept reader may not be null"); + + LOGGER.entry("reading Apex concept into a String . . ."); + + // Get the Apex concept as a string + String apexConceptString = null; + try { + apexConceptString = TextFileUtils.getReaderAsString(apexConceptReader).trim(); + } + catch (final IOException e) { + throw new ApexModelException("Unable to read Apex concept ", e); + } + + return read(apexConceptString); + } + + /** + * This method reads the specified Apex string into an Apex concept. + * + * @param apexConceptString the apex concept as a string + * @return the Apex concept + * @throws ApexModelException on reading exceptions + */ + public C read(final String apexConceptString) throws ApexModelException { + Assertions.argumentNotNull(apexConceptString, "concept string may not be null"); + + LOGGER.entry("reading Apex concept from string . . ."); + + final String 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 StreamSource source = new StreamSource(new StringReader(apexString)); + final JAXBElement<C> rootElement = unmarshaller.unmarshal(source, rootConceptClass); + apexConcept = rootElement.getValue(); + } + catch (final JAXBException e) { + throw new ApexModelException("Unable to unmarshal Apex concept ", e); + } + + LOGGER.debug("reading of Apex concept {} completed"); + + // Check if the concept should be validated + if (validateFlag) { + // Validate the configuration file + final AxValidationResult validationResult = apexConcept.validate(new AxValidationResult()); + LOGGER.debug(validationResult.toString()); + if (validationResult.isValid()) { + return apexConcept; + } + else { + LOGGER.error("Apex concept validation failed" + validationResult.toString()); + throw new ApexModelException("Apex concept validation failed" + validationResult.toString()); + } + } + else { + // No validation check + 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 marshaller 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 marshaller 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"); + } + } + +} |