#ifndef LENS_TYPE_HPP_INCLUDED
#define LENS_TYPE_HPP_INCLUDED

#include <iostream>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include <NBO/NBO/AnnotationRef.h>
#include <NBO/NBO/Denomination_Type.h>
#include <NBO/NBO/LensGeometry_Type.h>
#include <NBO/NBO/LensID_Type.h>
#include <NBO/NBO/LensShapeType_Type.h>
#include <NBO/NBO/ManufacturerSpec_Type.h>
#include <NBO/NBO/OpticalMaterialName_Type.h>
#include <NBO/NBO/UnitsDensity_Type.h>
#include <NBO/NBO/UnitsLength_Type.h>
#include <NBO/NBO/ENBOType.h>
#include <NBO/NBOGlobal.h>
#include <NBO/Shared/Base/NBOBaseClass.h>


namespace Inscoper::NBO {

/*!
* \brief Represents the XML complex type Lens.
*
* This element describes additional lenses positioned in the Light Path for one or more Channels available for this Instrument. A Lens is a component of glass or transparent plastic material, usually circular, with two primary surfaces that are ground and polished in a specific manner designed to produce either a convergence or divergence of light passing through the material. An Instrument may have several Lenses with different functions, such as a Magnification Changer (also known as Optovar), a Coupling Lens connecting the Light Source with the Microscope Stand, a Relay Lens positioned at the Detector mount, or additional Lenses placed in the Light Path for various purposes. This element can be associated with an optional Optics Turret.
*/
class NBO_EXPORT Lens_Type : public ManufacturerSpec_Type {

public:
	
	Lens_Type();
	~Lens_Type();

	/*!
	* \brief Cast a NBOBaseClass to a Lens_Type.
	*
	* \param base The base class to cast
	* \return The casted element, or nullptr if the cast fails
	*/
	static std::shared_ptr<Lens_Type> fromBase(NBOBaseClassPtr base);

	/*!
	* \brief Returns the class type name.
	*
	* \return The class type name
	*/
	virtual std::string getTypeName() const override;

	/*!
	* \brief Returns the XML element name corresponding to this class.
	*
	* \return The XML element name
	*/
	std::string getXMLName() const override;

	/*!
	* \brief Returns the NBO Type corresponding to this class.
	*
	* \return The NBO Type value
	*/
	ENBOType getNBOType() const override;

	/*!
	* \brief Returns a list of all classes derived from this class.
	*
	* \return The list of derived classes
	*/
	std::vector<NBOBaseClassPtr> getChildren() const override;

	/*!
	* \brief Returns a list of all child elements contained in this class.
	*
	* \return The list of child classes
	*/
	std::vector<NBOBaseClassPtr> getSubElements() const override;

	/*!
	* \brief Populates this object from a JSON file.
	*
	* \param path The path to the JSON file
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void fromJsonFile(const std::string& path, bool validate = true);

	/*!
	* \brief Populates this object from a JSON string.
	*
	* \param json_string The JSON content as a string
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void fromJsonString(const std::string& json_string, bool validate = true);

	/*!
	* \brief Populates this object from a XML file.
	*
	* \param path The path to the XML file
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void fromXmlFile(const std::string& path, bool validate = true);

	/*!
	* \brief Populates this object from a XML string.
	*
	* \param xml_string The XML content as a string
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void fromXmlString(const std::string& xml_string, bool validate = true);

	/*!
	* \brief Serializes this object to an XML file.
	*
	* \param filename The path to the output XML file
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void toXmlFile(const std::string& filename, bool validate = true) const;

	/*!
	* \brief Serializes this object to an XML string.
	*
	* \param validate If true, validates constraints on value. Default is true.
	* \return A string containing the XML representation of this object
	*/
	std::string toXmlString(bool validate = true) const;

	/*!
	* \brief Sets the value of the ID attribute.
	*
	* A Unique Identifier for this component.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setID(const Inscoper::NBO::LensID_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the ID attribute.
	*
	* A Unique Identifier for this component.
	*
	* \return The value of the attribute
	*/
	LensID_TypePtr getID() const;

	/*!
	* \brief Resets the ID attribute to an unset state.
	*
	* A Unique Identifier for this component.
	*/
	void resetID();

	/*!
	* \brief Checks whether the optional ID attribute is present.
	*
	* A Unique Identifier for this component.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasID() const;

	/*!
	* \brief Sets the value of the Name attribute.
	*
	* A User-defined Name for this component.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setName(const Inscoper::NBO::Denomination_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Name attribute.
	*
	* A User-defined Name for this component.
	*
	* \return The value of the attribute
	*/
	Denomination_TypePtr getName() const;

	/*!
	* \brief Resets the Name attribute to an unset state.
	*
	* A User-defined Name for this component.
	*/
	void resetName();

	/*!
	* \brief Checks whether the optional Name attribute is present.
	*
	* A User-defined Name for this component.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasName() const;

	/*!
	* \brief Sets the value of the Magnification attribute.
	*
	* This field records the nominal Magnification provided by this Lens as specified by the Manufacturer.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMagnification(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the Magnification attribute.
	*
	* This field records the nominal Magnification provided by this Lens as specified by the Manufacturer.
	*
	* \return The value of the attribute
	*/
	float getMagnification() const;

	/*!
	* \brief Resets the Magnification attribute to an unset state.
	*
	* This field records the nominal Magnification provided by this Lens as specified by the Manufacturer.
	*/
	void resetMagnification();

	/*!
	* \brief Checks whether the Magnification attribute is present.
	*
	* This field records the nominal Magnification provided by this Lens as specified by the Manufacturer.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasMagnification() const;

	/*!
	* \brief Sets the value of the LensNA attribute.
	*
	* This field captures the Numerical Aperture (NA) of this Lens expressed as a floating-point (real) number. NA is a number that was defined initially by Abbe to characterize Objectives and Condensers. NA can be calculated by the expression n sin alpha, where n is the Refractive Index of the medium between the Lens and the Sample, and alpha is half the Angular Aperture of the Lens. NA is a measure of how much of the illumination that leaves the specimen actually passes through the Lens. The larger the NA, the more information the lens can transmit. Expected range 0.02 - 1.5.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setLensNA(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the LensNA attribute.
	*
	* This field captures the Numerical Aperture (NA) of this Lens expressed as a floating-point (real) number. NA is a number that was defined initially by Abbe to characterize Objectives and Condensers. NA can be calculated by the expression n sin alpha, where n is the Refractive Index of the medium between the Lens and the Sample, and alpha is half the Angular Aperture of the Lens. NA is a measure of how much of the illumination that leaves the specimen actually passes through the Lens. The larger the NA, the more information the lens can transmit. Expected range 0.02 - 1.5.
	*
	* \return The value of the attribute
	*/
	float getLensNA() const;

	/*!
	* \brief Resets the LensNA attribute to an unset state.
	*
	* This field captures the Numerical Aperture (NA) of this Lens expressed as a floating-point (real) number. NA is a number that was defined initially by Abbe to characterize Objectives and Condensers. NA can be calculated by the expression n sin alpha, where n is the Refractive Index of the medium between the Lens and the Sample, and alpha is half the Angular Aperture of the Lens. NA is a measure of how much of the illumination that leaves the specimen actually passes through the Lens. The larger the NA, the more information the lens can transmit. Expected range 0.02 - 1.5.
	*/
	void resetLensNA();

	/*!
	* \brief Checks whether the LensNA attribute is present.
	*
	* This field captures the Numerical Aperture (NA) of this Lens expressed as a floating-point (real) number. NA is a number that was defined initially by Abbe to characterize Objectives and Condensers. NA can be calculated by the expression n sin alpha, where n is the Refractive Index of the medium between the Lens and the Sample, and alpha is half the Angular Aperture of the Lens. NA is a measure of how much of the illumination that leaves the specimen actually passes through the Lens. The larger the NA, the more information the lens can transmit. Expected range 0.02 - 1.5.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasLensNA() const;

	/*!
	* \brief Sets the value of the Infinity attribute.
	*
	* This field records whether (True) or not (False) this Lens is infinity corrected. An Infinity-corrected Lens is fixed for an infinite sample to primary Image distance. It needs to be used with a Tube Lens of appropriate focal length to obtain the specified magnification.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setInfinity(const bool& value, bool validate = true);

	/*!
	* \brief Returns the value of the Infinity attribute.
	*
	* This field records whether (True) or not (False) this Lens is infinity corrected. An Infinity-corrected Lens is fixed for an infinite sample to primary Image distance. It needs to be used with a Tube Lens of appropriate focal length to obtain the specified magnification.
	*
	* \return The value of the attribute
	*/
	bool getInfinity() const;

	/*!
	* \brief Resets the Infinity attribute to an unset state.
	*
	* This field records whether (True) or not (False) this Lens is infinity corrected. An Infinity-corrected Lens is fixed for an infinite sample to primary Image distance. It needs to be used with a Tube Lens of appropriate focal length to obtain the specified magnification.
	*/
	void resetInfinity();

	/*!
	* \brief Checks whether the Infinity attribute is present.
	*
	* This field records whether (True) or not (False) this Lens is infinity corrected. An Infinity-corrected Lens is fixed for an infinite sample to primary Image distance. It needs to be used with a Tube Lens of appropriate focal length to obtain the specified magnification.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasInfinity() const;

	/*!
	* \brief Sets the value of the Composite attribute.
	*
	* This field records whether this Lens is Composite (i.e., composed of multiple Lenses; True) or Simple (False).
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setComposite(const bool& value, bool validate = true);

	/*!
	* \brief Returns the value of the Composite attribute.
	*
	* This field records whether this Lens is Composite (i.e., composed of multiple Lenses; True) or Simple (False).
	*
	* \return The value of the attribute
	*/
	bool getComposite() const;

	/*!
	* \brief Resets the Composite attribute to an unset state.
	*
	* This field records whether this Lens is Composite (i.e., composed of multiple Lenses; True) or Simple (False).
	*/
	void resetComposite();

	/*!
	* \brief Checks whether the Composite attribute is present.
	*
	* This field records whether this Lens is Composite (i.e., composed of multiple Lenses; True) or Simple (False).
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasComposite() const;

	/*!
	* \brief Sets the value of the Shape attribute.
	*
	* This field records the shape of the profile (e.g., concave vs. convex) of this Lens. Please note that this attribute is often used to classify Lenses into categories.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setShape(const Inscoper::NBO::LensShapeType_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Shape attribute.
	*
	* This field records the shape of the profile (e.g., concave vs. convex) of this Lens. Please note that this attribute is often used to classify Lenses into categories.
	*
	* \return The value of the attribute
	*/
	LensShapeType_TypePtr getShape() const;

	/*!
	* \brief Resets the Shape attribute to an unset state.
	*
	* This field records the shape of the profile (e.g., concave vs. convex) of this Lens. Please note that this attribute is often used to classify Lenses into categories.
	*/
	void resetShape();

	/*!
	* \brief Checks whether the optional Shape attribute is present.
	*
	* This field records the shape of the profile (e.g., concave vs. convex) of this Lens. Please note that this attribute is often used to classify Lenses into categories.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasShape() const;

	/*!
	* \brief Sets the value of the Geometry attribute.
	*
	* The geometrical shape of this lens' surface(s).
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setGeometry(const Inscoper::NBO::LensGeometry_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the Geometry attribute.
	*
	* The geometrical shape of this lens' surface(s).
	*
	* \return The value of the attribute
	*/
	LensGeometry_TypePtr getGeometry() const;

	/*!
	* \brief Resets the Geometry attribute to an unset state.
	*
	* The geometrical shape of this lens' surface(s).
	*/
	void resetGeometry();

	/*!
	* \brief Checks whether the optional Geometry attribute is present.
	*
	* The geometrical shape of this lens' surface(s).
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasGeometry() const;

	/*!
	* \brief Sets the value of the Diameter attribute.
	*
	* This field records the physical diameter of this Lens.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setDiameter(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the Diameter attribute.
	*
	* This field records the physical diameter of this Lens.
	*
	* \return The value of the attribute
	*/
	float getDiameter() const;

	/*!
	* \brief Resets the Diameter attribute to an unset state.
	*
	* This field records the physical diameter of this Lens.
	*/
	void resetDiameter();

	/*!
	* \brief Checks whether the Diameter attribute is present.
	*
	* This field records the physical diameter of this Lens.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasDiameter() const;

	/*!
	* \brief Sets the value of the DiameterUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setDiameterUnit(const Inscoper::NBO::UnitsLength_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the DiameterUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsLength_TypePtr getDiameterUnit() const;

	/*!
	* \brief Resets the DiameterUnit attribute to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetDiameterUnit();

	/*!
	* \brief Checks whether the optional DiameterUnit attribute is present.
	*
	* No description available in the XSD standard.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasDiameterUnit() const;

	/*!
	* \brief Sets the value of the Coating attribute.
	*
	* An optical Coating consists of one or more thin layers of material deposited on an optical component such as a Lens or Mirror, which alters the way in which the optic reflects and transmits light. This field records the optical Coating used for this Lens.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setCoating(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the Coating attribute.
	*
	* An optical Coating consists of one or more thin layers of material deposited on an optical component such as a Lens or Mirror, which alters the way in which the optic reflects and transmits light. This field records the optical Coating used for this Lens.
	*
	* \return The value of the attribute
	*/
	std::string getCoating() const;

	/*!
	* \brief Resets the Coating attribute to an unset state.
	*
	* An optical Coating consists of one or more thin layers of material deposited on an optical component such as a Lens or Mirror, which alters the way in which the optic reflects and transmits light. This field records the optical Coating used for this Lens.
	*/
	void resetCoating();

	/*!
	* \brief Checks whether the Coating attribute is present.
	*
	* An optical Coating consists of one or more thin layers of material deposited on an optical component such as a Lens or Mirror, which alters the way in which the optic reflects and transmits light. This field records the optical Coating used for this Lens.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasCoating() const;

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* An optical Coating consists of one or more thin layers of material deposited on an optical component such as a Lens or Mirror, which alters the way in which the optic reflects and transmits light. This field records the optical Coating used for this Lens.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getCoatingAllowedValues();

	/*!
	* \brief Sets the value of the AttenuationCoefficient attribute.
	*
	* This field records the Attenuation Coefficient (AC) of this optical element. The AC (aka blocking coefficient) is a material property that characterizes the degree to which light is being blocked (i.e., scattered or absorbed) by it. AC is used as a measure of the out-of-band blocking of an optical Lens, Filter, Dichroic mirror over an extended range of the spectrum. AC is often reported in units of optical density (OD), whereas OD= -log10(T), and T=Transmittance (0≤T≤1).
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setAttenuationCoefficient(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the AttenuationCoefficient attribute.
	*
	* This field records the Attenuation Coefficient (AC) of this optical element. The AC (aka blocking coefficient) is a material property that characterizes the degree to which light is being blocked (i.e., scattered or absorbed) by it. AC is used as a measure of the out-of-band blocking of an optical Lens, Filter, Dichroic mirror over an extended range of the spectrum. AC is often reported in units of optical density (OD), whereas OD= -log10(T), and T=Transmittance (0≤T≤1).
	*
	* \return The value of the attribute
	*/
	float getAttenuationCoefficient() const;

	/*!
	* \brief Resets the AttenuationCoefficient attribute to an unset state.
	*
	* This field records the Attenuation Coefficient (AC) of this optical element. The AC (aka blocking coefficient) is a material property that characterizes the degree to which light is being blocked (i.e., scattered or absorbed) by it. AC is used as a measure of the out-of-band blocking of an optical Lens, Filter, Dichroic mirror over an extended range of the spectrum. AC is often reported in units of optical density (OD), whereas OD= -log10(T), and T=Transmittance (0≤T≤1).
	*/
	void resetAttenuationCoefficient();

	/*!
	* \brief Checks whether the AttenuationCoefficient attribute is present.
	*
	* This field records the Attenuation Coefficient (AC) of this optical element. The AC (aka blocking coefficient) is a material property that characterizes the degree to which light is being blocked (i.e., scattered or absorbed) by it. AC is used as a measure of the out-of-band blocking of an optical Lens, Filter, Dichroic mirror over an extended range of the spectrum. AC is often reported in units of optical density (OD), whereas OD= -log10(T), and T=Transmittance (0≤T≤1).
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasAttenuationCoefficient() const;

	/*!
	* \brief Sets the value of the WorkingDistance attribute.
	*
	* This field reports the Working Distance of this Lens under normal operating conditions. The Working Distance is the distance (in air, or in the specified immersion liquid) between the front of an Objective and the surface of the cover glass or of the specimen if uncovered.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setWorkingDistance(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the WorkingDistance attribute.
	*
	* This field reports the Working Distance of this Lens under normal operating conditions. The Working Distance is the distance (in air, or in the specified immersion liquid) between the front of an Objective and the surface of the cover glass or of the specimen if uncovered.
	*
	* \return The value of the attribute
	*/
	float getWorkingDistance() const;

	/*!
	* \brief Resets the WorkingDistance attribute to an unset state.
	*
	* This field reports the Working Distance of this Lens under normal operating conditions. The Working Distance is the distance (in air, or in the specified immersion liquid) between the front of an Objective and the surface of the cover glass or of the specimen if uncovered.
	*/
	void resetWorkingDistance();

	/*!
	* \brief Checks whether the WorkingDistance attribute is present.
	*
	* This field reports the Working Distance of this Lens under normal operating conditions. The Working Distance is the distance (in air, or in the specified immersion liquid) between the front of an Objective and the surface of the cover glass or of the specimen if uncovered.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasWorkingDistance() const;

	/*!
	* \brief Sets the value of the WorkingDistanceUnit attribute.
	*
	* This field reports the Working Distance of this Lens under normal operating conditions. The Working Distance is the distance (in air, or in the specified immersion liquid) between the front of an Objective and the surface of the cover glass or of the specimen if uncovered.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setWorkingDistanceUnit(const Inscoper::NBO::UnitsLength_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the WorkingDistanceUnit attribute.
	*
	* This field reports the Working Distance of this Lens under normal operating conditions. The Working Distance is the distance (in air, or in the specified immersion liquid) between the front of an Objective and the surface of the cover glass or of the specimen if uncovered.
	*
	* \return The value of the attribute
	*/
	UnitsLength_TypePtr getWorkingDistanceUnit() const;

	/*!
	* \brief Resets the WorkingDistanceUnit attribute to an unset state.
	*
	* This field reports the Working Distance of this Lens under normal operating conditions. The Working Distance is the distance (in air, or in the specified immersion liquid) between the front of an Objective and the surface of the cover glass or of the specimen if uncovered.
	*/
	void resetWorkingDistanceUnit();

	/*!
	* \brief Checks whether the optional WorkingDistanceUnit attribute is present.
	*
	* This field reports the Working Distance of this Lens under normal operating conditions. The Working Distance is the distance (in air, or in the specified immersion liquid) between the front of an Objective and the surface of the cover glass or of the specimen if uncovered.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasWorkingDistanceUnit() const;

	/*!
	* \brief Sets the value of the ImageDistance attribute.
	*
	* This field records the distance in air between the rear principal Plane of this Lens and the primary Image Plane.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setImageDistance(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the ImageDistance attribute.
	*
	* This field records the distance in air between the rear principal Plane of this Lens and the primary Image Plane.
	*
	* \return The value of the attribute
	*/
	float getImageDistance() const;

	/*!
	* \brief Resets the ImageDistance attribute to an unset state.
	*
	* This field records the distance in air between the rear principal Plane of this Lens and the primary Image Plane.
	*/
	void resetImageDistance();

	/*!
	* \brief Checks whether the ImageDistance attribute is present.
	*
	* This field records the distance in air between the rear principal Plane of this Lens and the primary Image Plane.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasImageDistance() const;

	/*!
	* \brief Sets the value of the ImageDistanceUnits attribute.
	*
	* No description available in the XSD standard.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setImageDistanceUnits(const Inscoper::NBO::UnitsLength_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the ImageDistanceUnits attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsLength_TypePtr getImageDistanceUnits() const;

	/*!
	* \brief Resets the ImageDistanceUnits attribute to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetImageDistanceUnits();

	/*!
	* \brief Checks whether the optional ImageDistanceUnits attribute is present.
	*
	* No description available in the XSD standard.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasImageDistanceUnits() const;

	/*!
	* \brief Sets the value of the FrontFocalLength attribute.
	*
	* This field records the distance (f) measured along the optical axis from the front principal Plane of this Lens to the front focal Plane (F).
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setFrontFocalLength(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the FrontFocalLength attribute.
	*
	* This field records the distance (f) measured along the optical axis from the front principal Plane of this Lens to the front focal Plane (F).
	*
	* \return The value of the attribute
	*/
	float getFrontFocalLength() const;

	/*!
	* \brief Resets the FrontFocalLength attribute to an unset state.
	*
	* This field records the distance (f) measured along the optical axis from the front principal Plane of this Lens to the front focal Plane (F).
	*/
	void resetFrontFocalLength();

	/*!
	* \brief Checks whether the FrontFocalLength attribute is present.
	*
	* This field records the distance (f) measured along the optical axis from the front principal Plane of this Lens to the front focal Plane (F).
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasFrontFocalLength() const;

	/*!
	* \brief Sets the value of the FrontFocalLengthUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setFrontFocalLengthUnit(const Inscoper::NBO::UnitsLength_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the FrontFocalLengthUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsLength_TypePtr getFrontFocalLengthUnit() const;

	/*!
	* \brief Resets the FrontFocalLengthUnit attribute to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetFrontFocalLengthUnit();

	/*!
	* \brief Checks whether the optional FrontFocalLengthUnit attribute is present.
	*
	* No description available in the XSD standard.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasFrontFocalLengthUnit() const;

	/*!
	* \brief Sets the value of the BackFocalLength attribute.
	*
	* This field records the distance (f') measured along the optical axis from the rear principal Plane of this Lens to the rear focal Plane (F').
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setBackFocalLength(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the BackFocalLength attribute.
	*
	* This field records the distance (f') measured along the optical axis from the rear principal Plane of this Lens to the rear focal Plane (F').
	*
	* \return The value of the attribute
	*/
	float getBackFocalLength() const;

	/*!
	* \brief Resets the BackFocalLength attribute to an unset state.
	*
	* This field records the distance (f') measured along the optical axis from the rear principal Plane of this Lens to the rear focal Plane (F').
	*/
	void resetBackFocalLength();

	/*!
	* \brief Checks whether the BackFocalLength attribute is present.
	*
	* This field records the distance (f') measured along the optical axis from the rear principal Plane of this Lens to the rear focal Plane (F').
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasBackFocalLength() const;

	/*!
	* \brief Sets the value of the BackFocalLengthUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setBackFocalLengthUnit(const Inscoper::NBO::UnitsLength_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the BackFocalLengthUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsLength_TypePtr getBackFocalLengthUnit() const;

	/*!
	* \brief Resets the BackFocalLengthUnit attribute to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetBackFocalLengthUnit();

	/*!
	* \brief Checks whether the optional BackFocalLengthUnit attribute is present.
	*
	* No description available in the XSD standard.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasBackFocalLengthUnit() const;

	/*!
	* \brief Sets the value of the RadiusOfCurvature attribute.
	*
	* This field records the Radius of Curvature of this Lens. A spherical Lens or Mirror surface has a center of curvature located either along or decentered from the system local optical axis. The vertex of the lens surface is located on the local optical axis. The distance from the vertex to the center of curvature is the Radius of Curvature of the surface.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setRadiusOfCurvature(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the RadiusOfCurvature attribute.
	*
	* This field records the Radius of Curvature of this Lens. A spherical Lens or Mirror surface has a center of curvature located either along or decentered from the system local optical axis. The vertex of the lens surface is located on the local optical axis. The distance from the vertex to the center of curvature is the Radius of Curvature of the surface.
	*
	* \return The value of the attribute
	*/
	float getRadiusOfCurvature() const;

	/*!
	* \brief Resets the RadiusOfCurvature attribute to an unset state.
	*
	* This field records the Radius of Curvature of this Lens. A spherical Lens or Mirror surface has a center of curvature located either along or decentered from the system local optical axis. The vertex of the lens surface is located on the local optical axis. The distance from the vertex to the center of curvature is the Radius of Curvature of the surface.
	*/
	void resetRadiusOfCurvature();

	/*!
	* \brief Checks whether the RadiusOfCurvature attribute is present.
	*
	* This field records the Radius of Curvature of this Lens. A spherical Lens or Mirror surface has a center of curvature located either along or decentered from the system local optical axis. The vertex of the lens surface is located on the local optical axis. The distance from the vertex to the center of curvature is the Radius of Curvature of the surface.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasRadiusOfCurvature() const;

	/*!
	* \brief Sets the value of the RadiusOfCurvatureUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setRadiusOfCurvatureUnit(const Inscoper::NBO::UnitsLength_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the RadiusOfCurvatureUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsLength_TypePtr getRadiusOfCurvatureUnit() const;

	/*!
	* \brief Resets the RadiusOfCurvatureUnit attribute to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetRadiusOfCurvatureUnit();

	/*!
	* \brief Checks whether the optional RadiusOfCurvatureUnit attribute is present.
	*
	* No description available in the XSD standard.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasRadiusOfCurvatureUnit() const;

	/*!
	* \brief Sets the value of the MaterialName attribute.
	*
	* This field records the chemical composition or designation of the Material this Lens is made of.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setMaterialName(const Inscoper::NBO::OpticalMaterialName_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the MaterialName attribute.
	*
	* This field records the chemical composition or designation of the Material this Lens is made of.
	*
	* \return The value of the attribute
	*/
	OpticalMaterialName_TypePtr getMaterialName() const;

	/*!
	* \brief Resets the MaterialName attribute to an unset state.
	*
	* This field records the chemical composition or designation of the Material this Lens is made of.
	*/
	void resetMaterialName();

	/*!
	* \brief Checks whether the optional MaterialName attribute is present.
	*
	* This field records the chemical composition or designation of the Material this Lens is made of.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasMaterialName() const;

	/*!
	* \brief Sets the value of the GlassCode attribute.
	*
	* If available, this field records the international Glass Code of the material that constitutes this Lens. The Glass Code designation is based on U.S. military standard MIL-G-174, and it consists of a six-digit number specifying the glass according to its Refractive Index nd at the Fraunhofer d- (or D3-) line, and its Abbe Number Vd also taken at that line. The resulting Glass Code is the value of nd-1 rounded to three digits, followed by Vd rounded to three digits, with all decimal points ignored. For example, BK7 has nd = 1.5168 and Vd = 64.17, giving a six-digit Glass Code of 517642.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setGlassCode(const std::string& value, bool validate = true);

	/*!
	* \brief Returns the value of the GlassCode attribute.
	*
	* If available, this field records the international Glass Code of the material that constitutes this Lens. The Glass Code designation is based on U.S. military standard MIL-G-174, and it consists of a six-digit number specifying the glass according to its Refractive Index nd at the Fraunhofer d- (or D3-) line, and its Abbe Number Vd also taken at that line. The resulting Glass Code is the value of nd-1 rounded to three digits, followed by Vd rounded to three digits, with all decimal points ignored. For example, BK7 has nd = 1.5168 and Vd = 64.17, giving a six-digit Glass Code of 517642.
	*
	* \return The value of the attribute
	*/
	std::string getGlassCode() const;

	/*!
	* \brief Resets the GlassCode attribute to an unset state.
	*
	* If available, this field records the international Glass Code of the material that constitutes this Lens. The Glass Code designation is based on U.S. military standard MIL-G-174, and it consists of a six-digit number specifying the glass according to its Refractive Index nd at the Fraunhofer d- (or D3-) line, and its Abbe Number Vd also taken at that line. The resulting Glass Code is the value of nd-1 rounded to three digits, followed by Vd rounded to three digits, with all decimal points ignored. For example, BK7 has nd = 1.5168 and Vd = 64.17, giving a six-digit Glass Code of 517642.
	*/
	void resetGlassCode();

	/*!
	* \brief Checks whether the GlassCode attribute is present.
	*
	* If available, this field records the international Glass Code of the material that constitutes this Lens. The Glass Code designation is based on U.S. military standard MIL-G-174, and it consists of a six-digit number specifying the glass according to its Refractive Index nd at the Fraunhofer d- (or D3-) line, and its Abbe Number Vd also taken at that line. The resulting Glass Code is the value of nd-1 rounded to three digits, followed by Vd rounded to three digits, with all decimal points ignored. For example, BK7 has nd = 1.5168 and Vd = 64.17, giving a six-digit Glass Code of 517642.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasGlassCode() const;

	/*!
	* \brief Returns the allowed values for this attribut.
	*
	* If available, this field records the international Glass Code of the material that constitutes this Lens. The Glass Code designation is based on U.S. military standard MIL-G-174, and it consists of a six-digit number specifying the glass according to its Refractive Index nd at the Fraunhofer d- (or D3-) line, and its Abbe Number Vd also taken at that line. The resulting Glass Code is the value of nd-1 rounded to three digits, followed by Vd rounded to three digits, with all decimal points ignored. For example, BK7 has nd = 1.5168 and Vd = 64.17, giving a six-digit Glass Code of 517642.
	*
	* \return The list of allowed values
	*/
	static const std::set<std::string>& getGlassCodeAllowedValues();

	/*!
	* \brief Sets the value of the RefractiveIndex attribute.
	*
	* This field records the Refractive Index of the material this Lens is made of, as specified by the Manufacturer. The Refractive Index is the ratio of the speed of light (more precisely, the phase velocity) in a vacuum versus that in a given medium.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setRefractiveIndex(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the RefractiveIndex attribute.
	*
	* This field records the Refractive Index of the material this Lens is made of, as specified by the Manufacturer. The Refractive Index is the ratio of the speed of light (more precisely, the phase velocity) in a vacuum versus that in a given medium.
	*
	* \return The value of the attribute
	*/
	float getRefractiveIndex() const;

	/*!
	* \brief Resets the RefractiveIndex attribute to an unset state.
	*
	* This field records the Refractive Index of the material this Lens is made of, as specified by the Manufacturer. The Refractive Index is the ratio of the speed of light (more precisely, the phase velocity) in a vacuum versus that in a given medium.
	*/
	void resetRefractiveIndex();

	/*!
	* \brief Checks whether the RefractiveIndex attribute is present.
	*
	* This field records the Refractive Index of the material this Lens is made of, as specified by the Manufacturer. The Refractive Index is the ratio of the speed of light (more precisely, the phase velocity) in a vacuum versus that in a given medium.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasRefractiveIndex() const;

	/*!
	* \brief Sets the value of the AbbeNumber attribute.
	*
	* This field records the Abbe number of this Lens. The Abbe Number is a measure of the material's dispersion (variation of Refractive Index versus Wavelength), with high values indicating low dispersion.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setAbbeNumber(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the AbbeNumber attribute.
	*
	* This field records the Abbe number of this Lens. The Abbe Number is a measure of the material's dispersion (variation of Refractive Index versus Wavelength), with high values indicating low dispersion.
	*
	* \return The value of the attribute
	*/
	float getAbbeNumber() const;

	/*!
	* \brief Resets the AbbeNumber attribute to an unset state.
	*
	* This field records the Abbe number of this Lens. The Abbe Number is a measure of the material's dispersion (variation of Refractive Index versus Wavelength), with high values indicating low dispersion.
	*/
	void resetAbbeNumber();

	/*!
	* \brief Checks whether the AbbeNumber attribute is present.
	*
	* This field records the Abbe number of this Lens. The Abbe Number is a measure of the material's dispersion (variation of Refractive Index versus Wavelength), with high values indicating low dispersion.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasAbbeNumber() const;

	/*!
	* \brief Sets the value of the Density attribute.
	*
	* This field records the Density of the material this Lens is made of.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setDensity(const float& value, bool validate = true);

	/*!
	* \brief Returns the value of the Density attribute.
	*
	* This field records the Density of the material this Lens is made of.
	*
	* \return The value of the attribute
	*/
	float getDensity() const;

	/*!
	* \brief Resets the Density attribute to an unset state.
	*
	* This field records the Density of the material this Lens is made of.
	*/
	void resetDensity();

	/*!
	* \brief Checks whether the Density attribute is present.
	*
	* This field records the Density of the material this Lens is made of.
	*
	* \return true if the attribute has been set, false otherwise
	*/
	bool hasDensity() const;

	/*!
	* \brief Sets the value of the DensityUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setDensityUnit(const Inscoper::NBO::UnitsDensity_TypePtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the DensityUnit attribute.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the attribute
	*/
	UnitsDensity_TypePtr getDensityUnit() const;

	/*!
	* \brief Resets the DensityUnit attribute to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetDensityUnit();

	/*!
	* \brief Checks whether the optional DensityUnit attribute is present.
	*
	* No description available in the XSD standard.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasDensityUnit() const;

	/*!
	* \brief Sets the value of the AnnotationRef element.
	*
	* No description available in the XSD standard.
	*
	* \param value The value to set
	* \param validate If true, validates constraints on value. Default is true.
	*/
	void setAnnotationRef(const Inscoper::NBO::AnnotationRefPtr& value, bool validate = true);

	/*!
	* \brief Returns the value of the AnnotationRef element.
	*
	* No description available in the XSD standard.
	*
	* \return The value of the element
	*/
	Inscoper::NBO::AnnotationRefPtr getAnnotationRef() const;

	/*!
	* \brief Resets the AnnotationRef element to an unset state.
	*
	* No description available in the XSD standard.
	*/
	void resetAnnotationRef();

	/*!
	* \brief Checks whether the optional AnnotationRef element is present.
	*
	* No description available in the XSD standard.
	*
	* \return true if the optional attribute has been set, false otherwise
	*/
	bool hasAnnotationRef() const;


private:
	class Impl;
	std::unique_ptr<Impl> pImpl;

	LensID_TypePtr ID = nullptr; // Required attribute
	Denomination_TypePtr Name = nullptr; // Optional attribute
    std::optional<float> Magnification; // Required attribute
    std::optional<float> LensNA; // Optional attribute
    std::optional<bool> Infinity; // Optional attribute
    std::optional<bool> Composite; // Required attribute
	LensShapeType_TypePtr Shape = nullptr; // Required attribute
	LensGeometry_TypePtr Geometry = nullptr; // Optional attribute
    std::optional<float> Diameter; // Optional attribute
	UnitsLength_TypePtr DiameterUnit = nullptr; // Optional attribute
    std::optional<std::string> Coating; // Optional attribute
    static const std::set<std::string> CoatingAllowedValues;
    std::optional<float> AttenuationCoefficient; // Optional attribute
    std::optional<float> WorkingDistance; // Optional attribute
	UnitsLength_TypePtr WorkingDistanceUnit = nullptr; // Optional attribute
    std::optional<float> ImageDistance; // Optional attribute
	UnitsLength_TypePtr ImageDistanceUnits = nullptr; // Optional attribute
    std::optional<float> FrontFocalLength; // Optional attribute
	UnitsLength_TypePtr FrontFocalLengthUnit = nullptr; // Optional attribute
    std::optional<float> BackFocalLength; // Optional attribute
	UnitsLength_TypePtr BackFocalLengthUnit = nullptr; // Optional attribute
    std::optional<float> RadiusOfCurvature; // Optional attribute
	UnitsLength_TypePtr RadiusOfCurvatureUnit = nullptr; // Optional attribute
	OpticalMaterialName_TypePtr MaterialName = nullptr; // Optional attribute
    std::optional<std::string> GlassCode; // Optional attribute
    static const std::set<std::string> GlassCodeAllowedValues;
    std::optional<float> RefractiveIndex; // Optional attribute
    std::optional<float> AbbeNumber; // Optional attribute
    std::optional<float> Density; // Optional attribute
	UnitsDensity_TypePtr DensityUnit = nullptr; // Optional attribute
    Inscoper::NBO::AnnotationRefPtr AnnotationRef = nullptr;
};

/*! Shared pointer for Lens_Type*/
typedef std::shared_ptr<Lens_Type> Lens_TypePtr;

} // namespace Inscoper::NBO

#endif // LENS_TYPE_HPP_INCLUDED