/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */
package org.apache.camel.component.fhir.springboot;

import java.util.List;
import java.util.Set;
import javax.annotation.Generated;
import org.apache.camel.spring.boot.DataFormatConfigurationPropertiesCommon;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * Marshall and unmarshall FHIR objects to/from JSON.
 * 
 * Generated by camel-package-maven-plugin - do not edit this file!
 */
@Generated("org.apache.camel.springboot.maven.SpringBootAutoConfigurationMojo")
@ConfigurationProperties(prefix = "camel.dataformat.fhirjson")
public class FhirJsonDataFormatConfiguration
        extends
            DataFormatConfigurationPropertiesCommon {

    /**
     * Whether to enable auto configuration of the fhirJson data format. This is
     * enabled by default.
     */
    private Boolean enabled;
    /**
     * The version of FHIR to use. Possible values are:
     * DSTU2,DSTU2_HL7ORG,DSTU2_1,DSTU3,R4
     */
    private String fhirVersion = "DSTU3";
    /**
     * Sets the pretty print flag, meaning that the parser will encode resources
     * with human-readable spacing and newlines between elements instead of
     * condensing output as much as possible.
     */
    private Boolean prettyPrint = false;
    /**
     * Sets the server's base URL used by this parser. If a value is set,
     * resource references will be turned into relative references if they are
     * provided as absolute URLs but have a base matching the given base.
     */
    private String serverBaseUrl;
    /**
     * If set to true (default is false) the ID of any resources being encoded
     * will not be included in the output. Note that this does not apply to
     * contained resources, only to root resources. In other words, if this is
     * set to true, contained resources will still have local IDs but the
     * outer/containing ID will not have an ID.
     */
    private Boolean omitResourceId = false;
    /**
     * If set to true (default is false), the values supplied to
     * setEncodeElements(Set) will not be applied to the root resource
     * (typically a Bundle), but will be applied to any sub-resources contained
     * within it (i.e. search result resources in that bundle)
     */
    private Boolean encodeElementsAppliesToChildResourcesOnly = false;
    /**
     * If provided, specifies the elements which should be encoded, to the
     * exclusion of all others. Valid values for this field would include:
     * Patient - Encode patient and all its children Patient.name - Encode only
     * the patient's name Patient.name.family - Encode only the patient's family
     * name .text - Encode the text element on any resource (only the very first
     * position may contain a wildcard) .(mandatory) - This is a special case
     * which causes any mandatory fields (min 0) to be encoded
     */
    private Set<String> encodeElements;
    /**
     * If provided, specifies the elements which should NOT be encoded. Valid
     * values for this field would include: Patient - Don't encode patient and
     * all its children Patient.name - Don't encode the patient's name
     * Patient.name.family - Don't encode the patient's family name .text -
     * Don't encode the text element on any resource (only the very first
     * position may contain a wildcard) DSTU2 note: Note that values including
     * meta, such as Patient.meta will work for DSTU2 parsers, but values with
     * subelements on meta such as Patient.meta.lastUpdated will only work in
     * DSTU3 mode.
     */
    private Set<String> dontEncodeElements;
    /**
     * If set to true (which is the default), resource references containing a
     * version will have the version removed when the resource is encoded. This
     * is generally good behaviour because in most situations, references from
     * one resource to another should be to the resource by ID, not by ID and
     * version. In some cases though, it may be desirable to preserve the
     * version in resource links. In that case, this value should be set to
     * false. This method provides the ability to globally disable reference
     * encoding. If finer-grained control is needed, use
     * setDontStripVersionsFromReferencesAtPaths(List)
     */
    private Boolean stripVersionsFromReferences = false;
    /**
     * If set to true (which is the default), the Bundle.entry.fullUrl will
     * override the Bundle.entry.resource's resource id if the fullUrl is
     * defined. This behavior happens when parsing the source data into a Bundle
     * object. Set this to false if this is not the desired behavior (e.g. the
     * client code wishes to perform additional validation checks between the
     * fullUrl and the resource id).
     */
    private Boolean overrideResourceIdWithBundleEntryFullUrl = false;
    /**
     * If set to true (default is false) only elements marked by the FHIR
     * specification as being summary elements will be included.
     */
    private Boolean summaryMode = false;
    /**
     * If set to true (default is false), narratives will not be included in the
     * encoded values.
     */
    private Boolean suppressNarratives = false;
    /**
     * If supplied value(s), any resource references at the specified paths will
     * have their resource versions encoded instead of being automatically
     * stripped during the encoding process. This setting has no effect on the
     * parsing process. This method provides a finer-grained level of control
     * than setStripVersionsFromReferences(String) and any paths specified by
     * this method will be encoded even if
     * setStripVersionsFromReferences(String) has been set to true (which is the
     * default)
     */
    private List<String> dontStripVersionsFromReferencesAtPaths;
    /**
     * Whether the data format should set the Content-Type header with the type
     * from the data format. For example application/xml for data formats
     * marshalling to XML, or application/json for data formats marshalling to
     * JSON
     */
    private Boolean contentTypeHeader = true;

    public String getFhirVersion() {
        return fhirVersion;
    }

    public void setFhirVersion(String fhirVersion) {
        this.fhirVersion = fhirVersion;
    }

    public Boolean getPrettyPrint() {
        return prettyPrint;
    }

    public void setPrettyPrint(Boolean prettyPrint) {
        this.prettyPrint = prettyPrint;
    }

    public String getServerBaseUrl() {
        return serverBaseUrl;
    }

    public void setServerBaseUrl(String serverBaseUrl) {
        this.serverBaseUrl = serverBaseUrl;
    }

    public Boolean getOmitResourceId() {
        return omitResourceId;
    }

    public void setOmitResourceId(Boolean omitResourceId) {
        this.omitResourceId = omitResourceId;
    }

    public Boolean getEncodeElementsAppliesToChildResourcesOnly() {
        return encodeElementsAppliesToChildResourcesOnly;
    }

    public void setEncodeElementsAppliesToChildResourcesOnly(
            Boolean encodeElementsAppliesToChildResourcesOnly) {
        this.encodeElementsAppliesToChildResourcesOnly = encodeElementsAppliesToChildResourcesOnly;
    }

    public Set<String> getEncodeElements() {
        return encodeElements;
    }

    public void setEncodeElements(Set<String> encodeElements) {
        this.encodeElements = encodeElements;
    }

    public Set<String> getDontEncodeElements() {
        return dontEncodeElements;
    }

    public void setDontEncodeElements(Set<String> dontEncodeElements) {
        this.dontEncodeElements = dontEncodeElements;
    }

    public Boolean getStripVersionsFromReferences() {
        return stripVersionsFromReferences;
    }

    public void setStripVersionsFromReferences(
            Boolean stripVersionsFromReferences) {
        this.stripVersionsFromReferences = stripVersionsFromReferences;
    }

    public Boolean getOverrideResourceIdWithBundleEntryFullUrl() {
        return overrideResourceIdWithBundleEntryFullUrl;
    }

    public void setOverrideResourceIdWithBundleEntryFullUrl(
            Boolean overrideResourceIdWithBundleEntryFullUrl) {
        this.overrideResourceIdWithBundleEntryFullUrl = overrideResourceIdWithBundleEntryFullUrl;
    }

    public Boolean getSummaryMode() {
        return summaryMode;
    }

    public void setSummaryMode(Boolean summaryMode) {
        this.summaryMode = summaryMode;
    }

    public Boolean getSuppressNarratives() {
        return suppressNarratives;
    }

    public void setSuppressNarratives(Boolean suppressNarratives) {
        this.suppressNarratives = suppressNarratives;
    }

    public List<String> getDontStripVersionsFromReferencesAtPaths() {
        return dontStripVersionsFromReferencesAtPaths;
    }

    public void setDontStripVersionsFromReferencesAtPaths(
            List<String> dontStripVersionsFromReferencesAtPaths) {
        this.dontStripVersionsFromReferencesAtPaths = dontStripVersionsFromReferencesAtPaths;
    }

    public Boolean getContentTypeHeader() {
        return contentTypeHeader;
    }

    public void setContentTypeHeader(Boolean contentTypeHeader) {
        this.contentTypeHeader = contentTypeHeader;
    }
}