/*
 * Copyright 2015-2018 OpenEstate.org.
 *
 * 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.
 */
package org.openestate.io.openimmo.converters;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.jaxen.JaxenException;
import org.openestate.io.core.XmlConverter;
import org.openestate.io.core.XmlUtils;
import org.openestate.io.openimmo.OpenImmoDocument;
import org.openestate.io.openimmo.OpenImmoFeedbackDocument;
import org.openestate.io.openimmo.OpenImmoTransferDocument;
import org.openestate.io.openimmo.OpenImmoUtils;
import org.openestate.io.openimmo.OpenImmoVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Converter for version 1.2.5.
 *
 * @author Andreas Rudolph
 * @since 1.0
 */
@SuppressWarnings({"SpellCheckingInspection", "WeakerAccess"})
public class OpenImmo_1_2_5 extends XmlConverter<OpenImmoDocument, OpenImmoVersion> {
    @SuppressWarnings("unused")
    private final static Logger LOGGER = LoggerFactory.getLogger(OpenImmo_1_2_5.class);

    @Override
    public OpenImmoVersion getVersion() {
        return OpenImmoVersion.V1_2_5;
    }

    /**
     * Downgrade an OpenImmo document from version 1.2.5 to 1.2.4.
     *
     * @param doc OpenImmo document in version 1.2.5
     */
    @Override
    public void downgradeToPreviousVersion(OpenImmoDocument doc) {
        doc.setDocumentVersion(OpenImmoVersion.V1_2_4);

        // downgrade a feedback document
        if (doc instanceof OpenImmoFeedbackDocument) {
            try {
                this.removeFeedbackObjektChildElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't remove unsupported children of <objekt> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }
        }

        // downgrade a transfer document
        else if (doc instanceof OpenImmoTransferDocument) {
            try {
                this.removeKontaktpersonChildElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't remove unsupported children of <kontaktperson> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.removeMwstGesamtElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't remove unsupported <mwst_gesamt> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.removeVerkehrswertElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't remove unsupported <verkehrswert> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.removeAnzahlLogiaElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't remove unsupported <anzahl_logia> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.removeErschliessungUmfangElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't remove unsupported <erschliessung_umfang> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.removeVerwaltungTechnChildElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't remove unsupported children of <verwaltung_techn> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.downgradeZustandElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't downgrade <zustand> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.downgradeBebaubarNachElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't downgrade <bebaubar_nach> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.downgradeErschliessungElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't downgrade <erschliessung> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.downgradeWohnungElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't downgrade <wohnung> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.downgradeHausElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't downgrade <haus> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }

            try {
                this.downgradeEnergiepassElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't downgrade <energiepass> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }
        }
    }

    /**
     * Upgrade an OpenImmo document from version 1.2.4 to 1.2.5.
     *
     * @param doc OpenImmo document in version 1.2.4
     */
    @Override
    @SuppressWarnings("Duplicates")
    public void upgradeFromPreviousVersion(OpenImmoDocument doc) {
        doc.setDocumentVersion(OpenImmoVersion.V1_2_5);

        if (doc instanceof OpenImmoTransferDocument) {
            try {
                this.upgradeEnergiepassElements(doc.getDocument());
            } catch (Exception ex) {
                LOGGER.error("Can't upgrade <energiepass> elements!");
                LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            }
        }
    }

    /**
     * Downgrade <bebaubar_nach> elements to OpenImmo 1.2.4.
     *

     * The option "BAULAND_OHNE_B_PLAN" for the "bebaubar_attr" attribute of
     * <bebaubar_nach> elements is not available in version 1.2.4.
     *

     * Any occurences of these values are removed.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void downgradeBebaubarNachElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:zustand_angaben/io:bebaubar_nach[@bebaubar_attr]",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            String value = StringUtils.trimToNull(node.getAttribute("bebaubar_attr"));
            if ("BAULAND_OHNE_B_PLAN".equalsIgnoreCase(value))
                node.removeAttribute("bebaubar_attr");
        }
    }

    /**
     * Downgrade <energiepass> elements to OpenImmo 1.2.4.
     *

     * The child elements <hwbwert>, <hwbklasse>,
     * <fgeewert>, <fgeeklasse> are copied into separate
     * <user_defined_simplefield> elements as it was
     * suggested by OpenImmo e.V..
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void downgradeEnergiepassElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:zustand_angaben/io:energiepass",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            Element parentNode = (Element) node.getParentNode();
            boolean hwbwertPassed = false;
            boolean hwbklassePassed = false;
            boolean fgeewertPassed = false;
            boolean fgeeklassePassed = false;
            List childNodes;

            // create a <user_defined_simplefield> for <hwbwert> elements
            childNodes = XmlUtils.newXPath("io:hwbwert", doc)
                    .selectNodes(node);
            for (Object childItem : childNodes) {
                Node childNode = (Node) childItem;
                if (!hwbwertPassed) {
                    String value = StringUtils.trimToNull(childNode.getTextContent());
                    if (value != null) {
                        parentNode.appendChild(OpenImmoUtils.createUserDefinedSimplefield(doc, "epass_hwbwert", value));
                        hwbwertPassed = true;
                    }
                }
                node.removeChild(childNode);
            }

            // create a <user_defined_simplefield> for <hwbklasse> elements
            childNodes = XmlUtils.newXPath("io:hwbklasse", doc)
                    .selectNodes(node);
            for (Object childItem : childNodes) {
                Node childNode = (Node) childItem;
                if (!hwbklassePassed) {
                    String value = StringUtils.trimToNull(childNode.getTextContent());
                    if (value != null) {
                        parentNode.appendChild(OpenImmoUtils.createUserDefinedSimplefield(doc, "epass_hwbklasse", value));
                        hwbklassePassed = true;
                    }
                }
                node.removeChild(childNode);
            }

            // create a <user_defined_simplefield> for <fgeewert> elements
            childNodes = XmlUtils.newXPath("io:fgeewert", doc)
                    .selectNodes(node);
            for (Object childItem : childNodes) {
                Node childNode = (Node) childItem;
                if (!fgeewertPassed) {
                    String value = StringUtils.trimToNull(childNode.getTextContent());
                    if (value != null) {
                        parentNode.appendChild(OpenImmoUtils.createUserDefinedSimplefield(doc, "epass_fgeewert", value));
                        fgeewertPassed = true;
                    }
                }
                node.removeChild(childNode);
            }

            // create a <user_defined_simplefield> for <baujahr> elements
            childNodes = XmlUtils.newXPath("io:fgeeklasse", doc)
                    .selectNodes(node);
            for (Object childItem : childNodes) {
                Node childNode = (Node) childItem;
                if (!fgeeklassePassed) {
                    String value = StringUtils.trimToNull(childNode.getTextContent());
                    if (value != null) {
                        parentNode.appendChild(OpenImmoUtils.createUserDefinedSimplefield(doc, "epass_fgeeklasse", value));
                        fgeeklassePassed = true;
                    }
                }
                node.removeChild(childNode);
            }
        }
    }

    /**
     * Downgrade <erschliessung> elements to OpenImmo 1.2.4.
     *

     * The option "ORTSUEBLICHERSCHLOSSEN" for the "erschl_attr" attribute of
     * <erschliessung> elements is not available in version 1.2.4.
     *

     * Any occurence of these values are removed.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void downgradeErschliessungElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:zustand_angaben/io:erschliessung[@erschl_attr]",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            String value = StringUtils.trimToNull(node.getAttribute("erschl_attr"));
            if ("ORTSUEBLICHERSCHLOSSEN".equalsIgnoreCase(value))
                node.removeAttribute("erschl_attr");
        }
    }

    /**
     * Downgrade <haus> elements to OpenImmo 1.2.4.
     *

     * The option "FERTIGHAUS" for the "haustyp" attribute of <haus>
     * elements is not available in version 1.2.4.
     *

     * Any occurence of these values is replaced by the "KEINE_ANGABE" value.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void downgradeHausElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:objektkategorie/io:objektart/io:haus[@haustyp]",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            String value = StringUtils.trimToNull(node.getAttribute("haustyp"));
            if ("FERTIGHAUS".equalsIgnoreCase(value))
                node.setAttribute("haustyp", "KEINE_ANGABE");
        }
    }

    /**
     * Downgrade <wohnung> elements to OpenImmo 1.2.4.
     *

     * The option "ATTIKAWOHNUNG" for the "wohnungtyp" attribute of
     * <wohnung> elements is not available in version 1.2.4.
     *

     * Any occurence of these values is replaced by the "KEINE_ANGABE" value.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void downgradeWohnungElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:objektkategorie/io:objektart/io:wohnung[@wohnungtyp]",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            String value = StringUtils.trimToNull(node.getAttribute("wohnungtyp"));
            if ("ATTIKAWOHNUNG".equalsIgnoreCase(value))
                node.setAttribute("wohnungtyp", "KEINE_ANGABE");
        }
    }

    /**
     * Downgrade <zustand> elements to OpenImmo 1.2.4.
     *

     * The options "TEIL_SANIERT", "VOLL_SANIERT", "SANIERUNGSBEDUERFTIG" for the
     * "zustand_art" attribute of <zustand> elements are not available in
     * version 1.2.4.
     *

     * Any occurence of the "TEIL_SANIERT" value is replaced by the
     * "TEIL_VOLLSANIERT" value.
     *

     * Any occurence of the "VOLL_SANIERT" value is replaced by the
     * "TEIL_VOLLSANIERT" value.
     *

     * Any occurence of the "SANIERUNGSBEDUERFTIG" value is removed.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void downgradeZustandElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:zustand_angaben/io:zustand[@zustand_art]",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            String value = StringUtils.trimToNull(node.getAttribute("zustand_art"));
            if ("TEIL_SANIERT".equalsIgnoreCase(value))
                node.setAttribute("zustand_art", "TEIL_VOLLSANIERT");
            else if ("VOLL_SANIERT".equalsIgnoreCase(value))
                node.setAttribute("zustand_art", "TEIL_VOLLSANIERT");
            else if ("SANIERUNGSBEDUERFTIG".equalsIgnoreCase(value))
                node.removeAttribute("zustand_art");
        }
    }

    /**
     * Remove <anzahl_logia> elements.
     *

     * OpenImmo 1.2.4 does not support <anzahl_logia> elements.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void removeAnzahlLogiaElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:flaechen/io:anzahl_logia",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            Element parentNode = (Element) node.getParentNode();
            parentNode.removeChild(node);
        }
    }

    /**
     * Remove <erschliessung_umfang> elements.
     *

     * OpenImmo 1.2.4 does not support <erschliessung_umfang> elements.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void removeErschliessungUmfangElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:zustand_angaben/io:erschliessung_umfang",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            Element parentNode = (Element) node.getParentNode();
            parentNode.removeChild(node);
        }
    }

    /**
     * Remove unsupported children from all <objekt> elements in feedback
     * XML.
     *

     * OpenImmo 1.2.4 does not support the following children in feedback XML's
     * for <objekt> elements: <land>, <stadtbezirk>,
     * <anzahl_zimmer>, <flaeche>
     *

     * These elements are removed by this function.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void removeFeedbackObjektChildElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo_feedback/io:objekt/io:land |" +
                        "/io:openimmo_feedback/io:objekt/io:stadtbezirk |" +
                        "/io:openimmo_feedback/io:objekt/io:anzahl_zimmer |" +
                        "/io:openimmo_feedback/io:objekt/io:flaeche",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            Element parentNode = (Element) node.getParentNode();
            parentNode.removeChild(node);
        }
    }

    /**
     * Remove unsupported children from all <kontaktperson> elements.
     *

     * OpenImmo 1.2.4 does not support the following children for
     * <kontaktperson> elements: <position>,
     * <immobilientreuhaenderid>, <foto>
     *

     * These elements are removed by this function.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void removeKontaktpersonChildElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:kontaktperson/io:position |" +
                        "/io:openimmo/io:anbieter/io:immobilie/io:kontaktperson/io:immobilientreuhaenderid |" +
                        "/io:openimmo/io:anbieter/io:immobilie/io:kontaktperson/io:foto",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            Element parentNode = (Element) node.getParentNode();
            parentNode.removeChild(node);
        }
    }

    /**
     * Remove <mwst_gesamt> elements.
     *

     * OpenImmo 1.2.4 does not support <mwst_gesamt> elements.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void removeMwstGesamtElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:preise/io:mwst_gesamt",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            Element parentNode = (Element) node.getParentNode();
            parentNode.removeChild(node);
        }
    }

    /**
     * Remove <verkehrswert> elements.
     *

     * OpenImmo 1.2.4 does not support <verkehrswert> elements.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void removeVerkehrswertElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:versteigerung/io:verkehrswert",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            Element parentNode = (Element) node.getParentNode();
            parentNode.removeChild(node);
        }
    }

    /**
     * Remove unsupported children from all <verwaltung_techn> elements.
     *

     * OpenImmo 1.2.4 does not support the following children for
     * <verwaltung_techn> elements: <gruppen_kennung>, <master>,
     * <sprache>
     *

     * These elements are removed by this function.
     *
     * @param doc OpenImmo document in version 1.2.5
     * @throws JaxenException if xpath evaluation failed
     */
    protected void removeVerwaltungTechnChildElements(Document doc) throws JaxenException {
        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:verwaltung_techn/io:gruppen_kennung |" +
                        "/io:openimmo/io:anbieter/io:immobilie/io:verwaltung_techn/io:master |" +
                        "/io:openimmo/io:anbieter/io:immobilie/io:verwaltung_techn/io:sprache",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;
            Element parentNode = (Element) node.getParentNode();
            parentNode.removeChild(node);
        }
    }

    /**
     * Upgrade <energiepass> elements to OpenImmo 1.2.5.
     *

     * The <user_defined_simplefield> elements for Austria, that were
     * suggested by OpenImmo e.V., are explicitly supported in OpenImmo 1.2.5 as
     * child elements of <energiepass>. Any matching
     * <user_defined_simplefield> elements are moved into the
     * <energiepass> element.
     *
     * @param doc OpenImmo document in version 1.2.4
     * @throws JaxenException if xpath evaluation failed
     */
    @SuppressWarnings("Duplicates")
    protected void upgradeEnergiepassElements(Document doc) throws JaxenException {
        Map<String, String> fields = new HashMap<>();
        fields.put("hwbwert", "user_defined_simplefield[@feldname='epass_hwbwert']");
        fields.put("hwbklasse", "user_defined_simplefield[@feldname='epass_hwbklasse']");
        fields.put("fgeewert", "user_defined_simplefield[@feldname='epass_fgeewert']");
        fields.put("fgeeklasse", "user_defined_simplefield[@feldname='epass_fgeeklasse']");

        List nodes = XmlUtils.newXPath(
                "/io:openimmo/io:anbieter/io:immobilie/io:zustand_angaben",
                doc).selectNodes(doc);
        for (Object item : nodes) {
            Element node = (Element) item;

            Element energiepassNode = (Element) XmlUtils.newXPath(
                    "io:energiepass", doc).selectSingleNode(node);
            if (energiepassNode == null) {
                energiepassNode = doc.createElementNS(StringUtils.EMPTY, "energiepass");
            }
            for (Map.Entry<String, String> entry : fields.entrySet()) {
                boolean fieldProcessed = false;
                List childNodes = XmlUtils.newXPath(entry.getValue(), doc)
                        .selectNodes(node);
                for (Object childItem : childNodes) {
                    Node childNode = (Node) childItem;
                    if (!fieldProcessed) {
                        String value = StringUtils.trimToNull(childNode.getTextContent());
                        if (value != null) {
                            Element newElement = doc.createElementNS(StringUtils.EMPTY, entry.getKey());
                            newElement.setTextContent(value);
                            energiepassNode.appendChild(newElement);
                            fieldProcessed = true;
                        }
                    }
                    node.removeChild(childNode);
                }
            }
            if (energiepassNode.getParentNode() == null && energiepassNode.hasChildNodes()) {
                node.appendChild(energiepassNode);
            }
        }
    }
}


package org.openestate.io.is24_xml.xml;

import java.io.Serializable;
import javax.annotation.Generated;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlType;
import org.jvnet.jaxb2_commons.lang.CopyStrategy2;
import org.jvnet.jaxb2_commons.lang.CopyTo2;
import org.jvnet.jaxb2_commons.lang.Equals2;
import org.jvnet.jaxb2_commons.lang.EqualsStrategy2;
import org.jvnet.jaxb2_commons.lang.JAXBCopyStrategy;
import org.jvnet.jaxb2_commons.lang.JAXBEqualsStrategy;
import org.jvnet.jaxb2_commons.lang.JAXBToStringStrategy;
import org.jvnet.jaxb2_commons.lang.ToString2;
import org.jvnet.jaxb2_commons.lang.ToStringStrategy2;
import org.jvnet.jaxb2_commons.locator.ObjectLocator;
import org.jvnet.jaxb2_commons.locator.util.LocatorUtils;

/**
 *
Java class for BefeuerungsArtTyp complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType name="BefeuerungsArtTyp">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <all>
 *         <element name="KeineAngabe" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/>
 *         <element name="Erdwaerme" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/>
 *         <element name="Solarheizung" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/>
 *         <element name="Pelletheizung" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/>
 *         <element name="Gas" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/>
 *         <element name="Oel" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/>
 *         <element name="Fernwaerme" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/>
 *         <element name="Strom" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/>
 *         <element name="Kohle" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/>
 *       </all>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BefeuerungsArtTyp", propOrder = {

})
@Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
public class BefeuerungsArtTyp implements Serializable, Cloneable, CopyTo2, Equals2, ToString2
{

    @XmlElementRef(name = "KeineAngabe", namespace = "http://www.immobilienscout24.de/immobilientransfer", type = JAXBElement.class, required = false)
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    protected JAXBElement<Object> keineAngabe;
    @XmlElementRef(name = "Erdwaerme", namespace = "http://www.immobilienscout24.de/immobilientransfer", type = JAXBElement.class, required = false)
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    protected JAXBElement<Object> erdwaerme;
    @XmlElementRef(name = "Solarheizung", namespace = "http://www.immobilienscout24.de/immobilientransfer", type = JAXBElement.class, required = false)
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    protected JAXBElement<Object> solarheizung;
    @XmlElementRef(name = "Pelletheizung", namespace = "http://www.immobilienscout24.de/immobilientransfer", type = JAXBElement.class, required = false)
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    protected JAXBElement<Object> pelletheizung;
    @XmlElementRef(name = "Gas", namespace = "http://www.immobilienscout24.de/immobilientransfer", type = JAXBElement.class, required = false)
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    protected JAXBElement<Object> gas;
    @XmlElementRef(name = "Oel", namespace = "http://www.immobilienscout24.de/immobilientransfer", type = JAXBElement.class, required = false)
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    protected JAXBElement<Object> oel;
    @XmlElementRef(name = "Fernwaerme", namespace = "http://www.immobilienscout24.de/immobilientransfer", type = JAXBElement.class, required = false)
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    protected JAXBElement<Object> fernwaerme;
    @XmlElementRef(name = "Strom", namespace = "http://www.immobilienscout24.de/immobilientransfer", type = JAXBElement.class, required = false)
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    protected JAXBElement<Object> strom;
    @XmlElementRef(name = "Kohle", namespace = "http://www.immobilienscout24.de/immobilientransfer", type = JAXBElement.class, required = false)
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    protected JAXBElement<Object> kohle;

    /**
     * Gets the value of the keineAngabe property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public JAXBElement<Object> getKeineAngabe() {
        return keineAngabe;
    }

    /**
     * Sets the value of the keineAngabe property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public void setKeineAngabe(JAXBElement<Object> value) {
        this.keineAngabe = value;
    }

    /**
     * Gets the value of the erdwaerme property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public JAXBElement<Object> getErdwaerme() {
        return erdwaerme;
    }

    /**
     * Sets the value of the erdwaerme property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public void setErdwaerme(JAXBElement<Object> value) {
        this.erdwaerme = value;
    }

    /**
     * Gets the value of the solarheizung property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public JAXBElement<Object> getSolarheizung() {
        return solarheizung;
    }

    /**
     * Sets the value of the solarheizung property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public void setSolarheizung(JAXBElement<Object> value) {
        this.solarheizung = value;
    }

    /**
     * Gets the value of the pelletheizung property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public JAXBElement<Object> getPelletheizung() {
        return pelletheizung;
    }

    /**
     * Sets the value of the pelletheizung property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public void setPelletheizung(JAXBElement<Object> value) {
        this.pelletheizung = value;
    }

    /**
     * Gets the value of the gas property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public JAXBElement<Object> getGas() {
        return gas;
    }

    /**
     * Sets the value of the gas property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public void setGas(JAXBElement<Object> value) {
        this.gas = value;
    }

    /**
     * Gets the value of the oel property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public JAXBElement<Object> getOel() {
        return oel;
    }

    /**
     * Sets the value of the oel property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public void setOel(JAXBElement<Object> value) {
        this.oel = value;
    }

    /**
     * Gets the value of the fernwaerme property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public JAXBElement<Object> getFernwaerme() {
        return fernwaerme;
    }

    /**
     * Sets the value of the fernwaerme property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public void setFernwaerme(JAXBElement<Object> value) {
        this.fernwaerme = value;
    }

    /**
     * Gets the value of the strom property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public JAXBElement<Object> getStrom() {
        return strom;
    }

    /**
     * Sets the value of the strom property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public void setStrom(JAXBElement<Object> value) {
        this.strom = value;
    }

    /**
     * Gets the value of the kohle property.
     *
     * @return
     *     possible object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public JAXBElement<Object> getKohle() {
        return kohle;
    }

    /**
     * Sets the value of the kohle property.
     *
     * @param value
     *     allowed object is
     *     {@link JAXBElement }{@code <}{@link Object }{@code >}
     *
     */
    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public void setKohle(JAXBElement<Object> value) {
        this.kohle = value;
    }

    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public String toString() {
        final ToStringStrategy2 strategy = JAXBToStringStrategy.INSTANCE;
        final StringBuilder buffer = new StringBuilder();
        append(null, buffer, strategy);
        return buffer.toString();
    }

    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public StringBuilder append(ObjectLocator locator, StringBuilder buffer, ToStringStrategy2 strategy) {
        strategy.appendStart(locator, this, buffer);
        appendFields(locator, buffer, strategy);
        strategy.appendEnd(locator, this, buffer);
        return buffer;
    }

    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public StringBuilder appendFields(ObjectLocator locator, StringBuilder buffer, ToStringStrategy2 strategy) {
        {
            JAXBElement<Object> theKeineAngabe;
            theKeineAngabe = this.getKeineAngabe();
            strategy.appendField(locator, this, "keineAngabe", buffer, theKeineAngabe, (this.keineAngabe!= null));
        }
        {
            JAXBElement<Object> theErdwaerme;
            theErdwaerme = this.getErdwaerme();
            strategy.appendField(locator, this, "erdwaerme", buffer, theErdwaerme, (this.erdwaerme!= null));
        }
        {
            JAXBElement<Object> theSolarheizung;
            theSolarheizung = this.getSolarheizung();
            strategy.appendField(locator, this, "solarheizung", buffer, theSolarheizung, (this.solarheizung!= null));
        }
        {
            JAXBElement<Object> thePelletheizung;
            thePelletheizung = this.getPelletheizung();
            strategy.appendField(locator, this, "pelletheizung", buffer, thePelletheizung, (this.pelletheizung!= null));
        }
        {
            JAXBElement<Object> theGas;
            theGas = this.getGas();
            strategy.appendField(locator, this, "gas", buffer, theGas, (this.gas!= null));
        }
        {
            JAXBElement<Object> theOel;
            theOel = this.getOel();
            strategy.appendField(locator, this, "oel", buffer, theOel, (this.oel!= null));
        }
        {
            JAXBElement<Object> theFernwaerme;
            theFernwaerme = this.getFernwaerme();
            strategy.appendField(locator, this, "fernwaerme", buffer, theFernwaerme, (this.fernwaerme!= null));
        }
        {
            JAXBElement<Object> theStrom;
            theStrom = this.getStrom();
            strategy.appendField(locator, this, "strom", buffer, theStrom, (this.strom!= null));
        }
        {
            JAXBElement<Object> theKohle;
            theKohle = this.getKohle();
            strategy.appendField(locator, this, "kohle", buffer, theKohle, (this.kohle!= null));
        }
        return buffer;
    }

    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public Object clone() {
        return copyTo(createNewInstance());
    }

    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public Object copyTo(Object target) {
        final CopyStrategy2 strategy = JAXBCopyStrategy.INSTANCE;
        return copyTo(null, target, strategy);
    }

    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public Object copyTo(ObjectLocator locator, Object target, CopyStrategy2 strategy) {
        final Object draftCopy = ((target == null)?createNewInstance():target);
        if (draftCopy instanceof BefeuerungsArtTyp) {
            final BefeuerungsArtTyp copy = ((BefeuerungsArtTyp) draftCopy);
            {
                Boolean keineAngabeShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, (this.keineAngabe!= null));
                if (keineAngabeShouldBeCopiedAndSet == Boolean.TRUE) {
                    JAXBElement<Object> sourceKeineAngabe;
                    sourceKeineAngabe = this.getKeineAngabe();
                    @SuppressWarnings("unchecked")
                    JAXBElement<Object> copyKeineAngabe = ((JAXBElement<Object> ) strategy.copy(LocatorUtils.property(locator, "keineAngabe", sourceKeineAngabe), sourceKeineAngabe, (this.keineAngabe!= null)));
                    copy.setKeineAngabe(copyKeineAngabe);
                } else {
                    if (keineAngabeShouldBeCopiedAndSet == Boolean.FALSE) {
                        copy.keineAngabe = null;
                    }
                }
            }
            {
                Boolean erdwaermeShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, (this.erdwaerme!= null));
                if (erdwaermeShouldBeCopiedAndSet == Boolean.TRUE) {
                    JAXBElement<Object> sourceErdwaerme;
                    sourceErdwaerme = this.getErdwaerme();
                    @SuppressWarnings("unchecked")
                    JAXBElement<Object> copyErdwaerme = ((JAXBElement<Object> ) strategy.copy(LocatorUtils.property(locator, "erdwaerme", sourceErdwaerme), sourceErdwaerme, (this.erdwaerme!= null)));
                    copy.setErdwaerme(copyErdwaerme);
                } else {
                    if (erdwaermeShouldBeCopiedAndSet == Boolean.FALSE) {
                        copy.erdwaerme = null;
                    }
                }
            }
            {
                Boolean solarheizungShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, (this.solarheizung!= null));
                if (solarheizungShouldBeCopiedAndSet == Boolean.TRUE) {
                    JAXBElement<Object> sourceSolarheizung;
                    sourceSolarheizung = this.getSolarheizung();
                    @SuppressWarnings("unchecked")
                    JAXBElement<Object> copySolarheizung = ((JAXBElement<Object> ) strategy.copy(LocatorUtils.property(locator, "solarheizung", sourceSolarheizung), sourceSolarheizung, (this.solarheizung!= null)));
                    copy.setSolarheizung(copySolarheizung);
                } else {
                    if (solarheizungShouldBeCopiedAndSet == Boolean.FALSE) {
                        copy.solarheizung = null;
                    }
                }
            }
            {
                Boolean pelletheizungShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, (this.pelletheizung!= null));
                if (pelletheizungShouldBeCopiedAndSet == Boolean.TRUE) {
                    JAXBElement<Object> sourcePelletheizung;
                    sourcePelletheizung = this.getPelletheizung();
                    @SuppressWarnings("unchecked")
                    JAXBElement<Object> copyPelletheizung = ((JAXBElement<Object> ) strategy.copy(LocatorUtils.property(locator, "pelletheizung", sourcePelletheizung), sourcePelletheizung, (this.pelletheizung!= null)));
                    copy.setPelletheizung(copyPelletheizung);
                } else {
                    if (pelletheizungShouldBeCopiedAndSet == Boolean.FALSE) {
                        copy.pelletheizung = null;
                    }
                }
            }
            {
                Boolean gasShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, (this.gas!= null));
                if (gasShouldBeCopiedAndSet == Boolean.TRUE) {
                    JAXBElement<Object> sourceGas;
                    sourceGas = this.getGas();
                    @SuppressWarnings("unchecked")
                    JAXBElement<Object> copyGas = ((JAXBElement<Object> ) strategy.copy(LocatorUtils.property(locator, "gas", sourceGas), sourceGas, (this.gas!= null)));
                    copy.setGas(copyGas);
                } else {
                    if (gasShouldBeCopiedAndSet == Boolean.FALSE) {
                        copy.gas = null;
                    }
                }
            }
            {
                Boolean oelShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, (this.oel!= null));
                if (oelShouldBeCopiedAndSet == Boolean.TRUE) {
                    JAXBElement<Object> sourceOel;
                    sourceOel = this.getOel();
                    @SuppressWarnings("unchecked")
                    JAXBElement<Object> copyOel = ((JAXBElement<Object> ) strategy.copy(LocatorUtils.property(locator, "oel", sourceOel), sourceOel, (this.oel!= null)));
                    copy.setOel(copyOel);
                } else {
                    if (oelShouldBeCopiedAndSet == Boolean.FALSE) {
                        copy.oel = null;
                    }
                }
            }
            {
                Boolean fernwaermeShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, (this.fernwaerme!= null));
                if (fernwaermeShouldBeCopiedAndSet == Boolean.TRUE) {
                    JAXBElement<Object> sourceFernwaerme;
                    sourceFernwaerme = this.getFernwaerme();
                    @SuppressWarnings("unchecked")
                    JAXBElement<Object> copyFernwaerme = ((JAXBElement<Object> ) strategy.copy(LocatorUtils.property(locator, "fernwaerme", sourceFernwaerme), sourceFernwaerme, (this.fernwaerme!= null)));
                    copy.setFernwaerme(copyFernwaerme);
                } else {
                    if (fernwaermeShouldBeCopiedAndSet == Boolean.FALSE) {
                        copy.fernwaerme = null;
                    }
                }
            }
            {
                Boolean stromShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, (this.strom!= null));
                if (stromShouldBeCopiedAndSet == Boolean.TRUE) {
                    JAXBElement<Object> sourceStrom;
                    sourceStrom = this.getStrom();
                    @SuppressWarnings("unchecked")
                    JAXBElement<Object> copyStrom = ((JAXBElement<Object> ) strategy.copy(LocatorUtils.property(locator, "strom", sourceStrom), sourceStrom, (this.strom!= null)));
                    copy.setStrom(copyStrom);
                } else {
                    if (stromShouldBeCopiedAndSet == Boolean.FALSE) {
                        copy.strom = null;
                    }
                }
            }
            {
                Boolean kohleShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, (this.kohle!= null));
                if (kohleShouldBeCopiedAndSet == Boolean.TRUE) {
                    JAXBElement<Object> sourceKohle;
                    sourceKohle = this.getKohle();
                    @SuppressWarnings("unchecked")
                    JAXBElement<Object> copyKohle = ((JAXBElement<Object> ) strategy.copy(LocatorUtils.property(locator, "kohle", sourceKohle), sourceKohle, (this.kohle!= null)));
                    copy.setKohle(copyKohle);
                } else {
                    if (kohleShouldBeCopiedAndSet == Boolean.FALSE) {
                        copy.kohle = null;
                    }
                }
            }
        }
        return draftCopy;
    }

    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public Object createNewInstance() {
        return new BefeuerungsArtTyp();
    }

    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public boolean equals(ObjectLocator thisLocator, ObjectLocator thatLocator, Object object, EqualsStrategy2 strategy) {
        if ((object == null)||(this.getClass()!= object.getClass())) {
            return false;
        }
        if (this == object) {
            return true;
        }
        final BefeuerungsArtTyp that = ((BefeuerungsArtTyp) object);
        {
            JAXBElement<Object> lhsKeineAngabe;
            lhsKeineAngabe = this.getKeineAngabe();
            JAXBElement<Object> rhsKeineAngabe;
            rhsKeineAngabe = that.getKeineAngabe();
            if (!strategy.equals(LocatorUtils.property(thisLocator, "keineAngabe", lhsKeineAngabe), LocatorUtils.property(thatLocator, "keineAngabe", rhsKeineAngabe), lhsKeineAngabe, rhsKeineAngabe, (this.keineAngabe!= null), (that.keineAngabe!= null))) {
                return false;
            }
        }
        {
            JAXBElement<Object> lhsErdwaerme;
            lhsErdwaerme = this.getErdwaerme();
            JAXBElement<Object> rhsErdwaerme;
            rhsErdwaerme = that.getErdwaerme();
            if (!strategy.equals(LocatorUtils.property(thisLocator, "erdwaerme", lhsErdwaerme), LocatorUtils.property(thatLocator, "erdwaerme", rhsErdwaerme), lhsErdwaerme, rhsErdwaerme, (this.erdwaerme!= null), (that.erdwaerme!= null))) {
                return false;
            }
        }
        {
            JAXBElement<Object> lhsSolarheizung;
            lhsSolarheizung = this.getSolarheizung();
            JAXBElement<Object> rhsSolarheizung;
            rhsSolarheizung = that.getSolarheizung();
            if (!strategy.equals(LocatorUtils.property(thisLocator, "solarheizung", lhsSolarheizung), LocatorUtils.property(thatLocator, "solarheizung", rhsSolarheizung), lhsSolarheizung, rhsSolarheizung, (this.solarheizung!= null), (that.solarheizung!= null))) {
                return false;
            }
        }
        {
            JAXBElement<Object> lhsPelletheizung;
            lhsPelletheizung = this.getPelletheizung();
            JAXBElement<Object> rhsPelletheizung;
            rhsPelletheizung = that.getPelletheizung();
            if (!strategy.equals(LocatorUtils.property(thisLocator, "pelletheizung", lhsPelletheizung), LocatorUtils.property(thatLocator, "pelletheizung", rhsPelletheizung), lhsPelletheizung, rhsPelletheizung, (this.pelletheizung!= null), (that.pelletheizung!= null))) {
                return false;
            }
        }
        {
            JAXBElement<Object> lhsGas;
            lhsGas = this.getGas();
            JAXBElement<Object> rhsGas;
            rhsGas = that.getGas();
            if (!strategy.equals(LocatorUtils.property(thisLocator, "gas", lhsGas), LocatorUtils.property(thatLocator, "gas", rhsGas), lhsGas, rhsGas, (this.gas!= null), (that.gas!= null))) {
                return false;
            }
        }
        {
            JAXBElement<Object> lhsOel;
            lhsOel = this.getOel();
            JAXBElement<Object> rhsOel;
            rhsOel = that.getOel();
            if (!strategy.equals(LocatorUtils.property(thisLocator, "oel", lhsOel), LocatorUtils.property(thatLocator, "oel", rhsOel), lhsOel, rhsOel, (this.oel!= null), (that.oel!= null))) {
                return false;
            }
        }
        {
            JAXBElement<Object> lhsFernwaerme;
            lhsFernwaerme = this.getFernwaerme();
            JAXBElement<Object> rhsFernwaerme;
            rhsFernwaerme = that.getFernwaerme();
            if (!strategy.equals(LocatorUtils.property(thisLocator, "fernwaerme", lhsFernwaerme), LocatorUtils.property(thatLocator, "fernwaerme", rhsFernwaerme), lhsFernwaerme, rhsFernwaerme, (this.fernwaerme!= null), (that.fernwaerme!= null))) {
                return false;
            }
        }
        {
            JAXBElement<Object> lhsStrom;
            lhsStrom = this.getStrom();
            JAXBElement<Object> rhsStrom;
            rhsStrom = that.getStrom();
            if (!strategy.equals(LocatorUtils.property(thisLocator, "strom", lhsStrom), LocatorUtils.property(thatLocator, "strom", rhsStrom), lhsStrom, rhsStrom, (this.strom!= null), (that.strom!= null))) {
                return false;
            }
        }
        {
            JAXBElement<Object> lhsKohle;
            lhsKohle = this.getKohle();
            JAXBElement<Object> rhsKohle;
            rhsKohle = that.getKohle();
            if (!strategy.equals(LocatorUtils.property(thisLocator, "kohle", lhsKohle), LocatorUtils.property(thatLocator, "kohle", rhsKohle), lhsKohle, rhsKohle, (this.kohle!= null), (that.kohle!= null))) {
                return false;
            }
        }
        return true;
    }

    @Generated(value = "com.sun.tools.xjc.Driver", date = "2018-10-12T02:52:47+02:00", comments = "JAXB RI v2.2.11")
    public boolean equals(Object object) {
        final EqualsStrategy2 strategy = JAXBEqualsStrategy.INSTANCE;
        return equals(null, null, object, strategy);
    }

}


/*
 * Copyright 2015-2018 OpenEstate.org.
 *
 * 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.
 */
package org.openestate.io.examples;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.Currency;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.commons.io.output.NullWriter;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.PropertyConfigurator;
import org.openestate.io.examples.utils.RandomStringUtils;
import org.openestate.io.immobiliare_it.ImmobiliareItDocument;
import org.openestate.io.immobiliare_it.ImmobiliareItUtils;
import org.openestate.io.immobiliare_it.xml.Box;
import org.openestate.io.immobiliare_it.xml.BusinessElement;
import org.openestate.io.immobiliare_it.xml.ClassEnergy;
import org.openestate.io.immobiliare_it.xml.Clazz;
import org.openestate.io.immobiliare_it.xml.Feed;
import org.openestate.io.immobiliare_it.xml.Feed.Properties.Property;
import org.openestate.io.immobiliare_it.xml.Floor;
import org.openestate.io.immobiliare_it.xml.Furniture;
import org.openestate.io.immobiliare_it.xml.Garden;
import org.openestate.io.immobiliare_it.xml.Heat;
import org.openestate.io.immobiliare_it.xml.Kitchen;
import org.openestate.io.immobiliare_it.xml.LocationStructure.Locality.Neighbourhood.LocationNeighbourhoodType;
import org.openestate.io.immobiliare_it.xml.ObjectFactory;
import org.openestate.io.immobiliare_it.xml.Operation;
import org.openestate.io.immobiliare_it.xml.OwnershipType;
import org.openestate.io.immobiliare_it.xml.PictureExtended;
import org.openestate.io.immobiliare_it.xml.PictureProject;
import org.openestate.io.immobiliare_it.xml.PropertyType;
import org.openestate.io.immobiliare_it.xml.PropertyTypeBusiness;
import org.openestate.io.immobiliare_it.xml.PropertyTypeSimple;
import org.openestate.io.immobiliare_it.xml.Rental;
import org.openestate.io.immobiliare_it.xml.Status;
import org.openestate.io.immobiliare_it.xml.TerrainType;
import org.openestate.io.immobiliare_it.xml.VideoProject;
import org.openestate.io.immobiliare_it.xml.VideoType;
import org.openestate.io.immobiliare_it.xml.YesNoReady;
import org.openestate.io.immobiliare_it.xml.types.Category;
import org.openestate.io.immobiliare_it.xml.types.EnergyUnit;
import org.openestate.io.immobiliare_it.xml.types.LandSizeUnit;
import org.openestate.io.immobiliare_it.xml.types.SizeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Example for writing XML files for
 * immobiliare.it.
 *

 * This example illustrates the programmatic creation of documents for
 * immobiliare.it and how they are written
 * into XML.
 *
 * @author Andreas Rudolph
 * @since 1.0
 */
@SuppressWarnings("WeakerAccess")
public class ImmobiliareItWritingExample {
    @SuppressWarnings("unused")
    private final static Logger LOGGER = LoggerFactory.getLogger(ImmobiliareItWritingExample.class);
    private final static String PACKAGE = "/org/openestate/io/examples";
    private final static ObjectFactory FACTORY = ImmobiliareItUtils.getFactory();
    private final static boolean PRETTY_PRINT = true;

    /**
     * Start the example application.
     *
     * @param args command line arguments
     */
    @SuppressWarnings("Duplicates")
    public static void main(String[] args) {
        // init logging
        PropertyConfigurator.configure(
                ImmobiliareItWritingExample.class.getResource(PACKAGE + "/log4j.properties"));

        // create a Feed object with some example data
        // this object corresponds to the <feed> root element in XML
        Feed feed = FACTORY.createFeed();

        // append some example objects to the Feed object
        feed.setProperties(FACTORY.createFeedProperties());
        feed.getProperties().getProperty().add(createProperty());
        feed.getProperties().getProperty().add(createProperty());

        // convert the Feed object into a XML document
        ImmobiliareItDocument doc = null;
        try {
            doc = ImmobiliareItDocument.newDocument(feed);
        } catch (Exception ex) {
            LOGGER.error("Can't create XML document!");
            LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            System.exit(1);
        }

        // write XML document into a java.io.File
        try {
            write(doc, File.createTempFile("output-", ".xml"));
        } catch (IOException ex) {
            LOGGER.error("Can't create temporary file!");
            LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            System.exit(1);
        }

        // write XML document into a java.io.OutputStream
        write(doc, new NullOutputStream());

        // write XML document into a java.io.Writer
        write(doc, new NullWriter());

        // write XML document into a string and send it to the console
        writeToConsole(doc);
    }

    /**
     * Create a {@link Property} with some example data.
     *
     * @return created example object
     */
    protected static Property createProperty() {
        // create an example real estate for rent
        Property obj = FACTORY.createFeedPropertiesProperty();
        obj.setBuildingStatus(Status.ABITABILE);
        obj.setCategory(Category.COMMERCIALE);
        obj.setDateExpiration(Calendar.getInstance());
        obj.setDateUpdated(Calendar.getInstance());
        obj.setOperation(Operation.WRITE);
        obj.setUniqueId(RandomStringUtils.random(5));

        obj.setAgent(FACTORY.createFeedPropertiesPropertyAgent());
        obj.getAgent().setEmail("agency@test.org");
        obj.getAgent().setOfficeName("agency name");

        obj.setBlueprints(FACTORY.createFeedPropertiesPropertyBlueprints());
        obj.getBlueprints().getBlueprint().add(createPictureExtended());
        obj.getBlueprints().getBlueprint().add(createPictureExtended());
        obj.getBlueprints().getBlueprint().add(createPictureExtended());

        obj.setBuilding(FACTORY.createBuilding());
        obj.getBuilding().setCategory(Category.COMMERCIALE);
        obj.getBuilding().setClazz(Clazz.SIGNORILE);
        obj.getBuilding().setDetail(PropertyTypeBusiness.ALBERGO);
        obj.getBuilding().setStatus(Status.DISCRETO);
        obj.getBuilding().setType(PropertyType.APPARTAMENTO);

        obj.setExtraFeatures(FACTORY.createFeedPropertiesPropertyExtraFeatures());
        obj.getExtraFeatures().setAirConditioning(RandomUtils.nextInt(0, 2) == 1);
        obj.getExtraFeatures().setBalcony(RandomUtils.nextInt(0, 2) == 1);
        obj.getExtraFeatures().setBathrooms(BigInteger.valueOf(RandomUtils.nextLong(1, 5)));
        obj.getExtraFeatures().setBeamHeight(BigInteger.valueOf(RandomUtils.nextLong(1, 10)));
        obj.getExtraFeatures().setBedrooms(BigInteger.valueOf(RandomUtils.nextLong(1, 5)));
        obj.getExtraFeatures().setBuildYear(RandomUtils.nextInt(1900, 2000));
        obj.getExtraFeatures().setDocDescription("some descriptions");
        obj.getExtraFeatures().setDocSpecification("some specifications");
        obj.getExtraFeatures().setElevator(RandomUtils.nextInt(0, 2) == 1);
        obj.getExtraFeatures().setFloorplannerUrl("http://floorplanner-url.it/");
        obj.getExtraFeatures().setFreeConditions("free conditions");
        obj.getExtraFeatures().setFurniture(Furniture.PARZIALMENTE_ARREDATO);
        obj.getExtraFeatures().setGarden(Garden.NESSUNO);
        obj.getExtraFeatures().setHeating(Heat.AUTONOMO);
        obj.getExtraFeatures().setKitchen(Kitchen.SEMI_ABITABILE);
        obj.getExtraFeatures().setNet(RandomUtils.nextInt(0, 2) == 1);
        obj.getExtraFeatures().setNumFloors(BigInteger.valueOf(RandomUtils.nextLong(1, 5)));
        obj.getExtraFeatures().setOverheadCrane(YesNoReady.READY);
        obj.getExtraFeatures().setReception(RandomUtils.nextInt(0, 2) == 1);
        obj.getExtraFeatures().setRentContract(Rental.LIBERO);
        obj.getExtraFeatures().setSecurityAlarm(RandomUtils.nextInt(0, 2) == 1);
        obj.getExtraFeatures().setTerrace(RandomUtils.nextInt(0, 2) == 1);
        obj.getExtraFeatures().setVirtualTour("virtual tour");

        obj.getExtraFeatures().setAdditionalCosts(FACTORY.createAdditionalCostsType());
        obj.getExtraFeatures().getAdditionalCosts().setCurrency(Currency.getInstance("EUR"));
        obj.getExtraFeatures().getAdditionalCosts().setValue(BigInteger.valueOf(RandomUtils.nextLong(0, 5000)));

        obj.getExtraFeatures().setExternalArea(FACTORY.createLandSizeType());
        obj.getExtraFeatures().getExternalArea().setUnit(LandSizeUnit.M2);
        obj.getExtraFeatures().getExternalArea().setValue(BigInteger.valueOf(RandomUtils.nextLong(50, 5000)));

        obj.getExtraFeatures().setFloor(FACTORY.createFloor());
        obj.getExtraFeatures().getFloor().setType(Floor.FloorType.INTERMEDIO);
        obj.getExtraFeatures().getFloor().setValue(BigInteger.valueOf(RandomUtils.nextLong(0, 10)));

        obj.getExtraFeatures().setGarage(FACTORY.createBox());
        obj.getExtraFeatures().getGarage().setType(Box.BoxType.POSTO_AUTO);
        obj.getExtraFeatures().getGarage().setValue(BigInteger.valueOf(RandomUtils.nextLong(0, 10)));

        obj.getExtraFeatures().setOfficeSize(FACTORY.createSizeType());
        obj.getExtraFeatures().getOfficeSize().setUnit(SizeUnit.M2);
        obj.getExtraFeatures().getOfficeSize().setValue(BigInteger.valueOf(RandomUtils.nextLong(5, 50)));

        obj.setFeatures(FACTORY.createFeedPropertiesPropertyFeatures());
        obj.getFeatures().setEnergyClass(ClassEnergy.D);
        obj.getFeatures().setRooms(RandomUtils.nextInt(1, 5));

        obj.getFeatures().setEnergyPerformance(FACTORY.createClassEnergyPerformance());
        obj.getFeatures().getEnergyPerformance().setCertified(RandomUtils.nextInt(0, 2) == 1);
        obj.getFeatures().getEnergyPerformance().setUnit(EnergyUnit.KWH_M2ANNO);
        obj.getFeatures().getEnergyPerformance().setValue("energy performance");

        obj.getFeatures().setPrice(FACTORY.createPriceType());
        obj.getFeatures().getPrice().setCurrency(Currency.getInstance("EUR"));
        obj.getFeatures().getPrice().setReserved(RandomUtils.nextInt(0, 2) == 1);
        obj.getFeatures().getPrice().setValue(BigInteger.valueOf(RandomUtils.nextLong(500, 5000000)));

        obj.getFeatures().setSize(FACTORY.createSizeType());
        obj.getFeatures().getSize().setUnit(SizeUnit.M2);
        obj.getFeatures().getSize().setValue(BigInteger.valueOf(RandomUtils.nextLong(50, 5000)));

        obj.setLocation(FACTORY.createLocationStructure());
        obj.getLocation().setAdministrativeArea("administrative area");
        obj.getLocation().setCountryCode("DE");

        obj.getLocation().setCity(FACTORY.createLocationStructureCity());
        obj.getLocation().getCity().setCode(BigInteger.ZERO);
        obj.getLocation().getCity().setValue("Berlin");

        obj.getLocation().setLocality(FACTORY.createLocationStructureLocality());
        obj.getLocation().getLocality().setLatitude(BigDecimal.valueOf(RandomUtils.nextDouble(0, 90)));
        obj.getLocation().getLocality().setLongitude(BigDecimal.valueOf(RandomUtils.nextDouble(0, 90)));
        obj.getLocation().getLocality().setPostalCode("13125");

        obj.getLocation().getLocality().setNeighbourhood(FACTORY.createLocationStructureLocalityNeighbourhood());
        obj.getLocation().getLocality().getNeighbourhood().setId(BigInteger.ZERO);
        obj.getLocation().getLocality().getNeighbourhood().setType(LocationNeighbourhoodType.DISTRICT);
        obj.getLocation().getLocality().getNeighbourhood().setValue("about the neighbourhood");

        obj.getLocation().getLocality().setThoroughfare(FACTORY.createLocationStructureLocalityThoroughfare());
        obj.getLocation().getLocality().getThoroughfare().setDisplay(RandomUtils.nextInt(0, 2) == 1);
        obj.getLocation().getLocality().getThoroughfare().setValue("about thoroughfare");

        obj.getLocation().setSubAdministrativeArea(FACTORY.createLocationStructureSubAdministrativeArea());
        obj.getLocation().getSubAdministrativeArea().setCode(RandomStringUtils.random(5));
        obj.getLocation().getSubAdministrativeArea().setValue("Berlin");

        obj.setPictures(FACTORY.createFeedPropertiesPropertyPictures());
        obj.getPictures().getPictureUrlAndPicture().add(createPicture());
        obj.getPictures().getPictureUrlAndPicture().add(createPicture());
        obj.getPictures().getPictureUrlAndPicture().add(createPicture());

        obj.setPropertyType(FACTORY.createProptype());
        obj.getPropertyType().setBusinessType(FACTORY.createBusinessElement());
        obj.getPropertyType().getBusinessType().setCategory(BusinessElement.BusinessElementCategory.IMMOBILE);
        obj.getPropertyType().getBusinessType().setValue(PropertyTypeBusiness.ALTRO);
        obj.getPropertyType().setTerrains(FACTORY.createTerrains());
        obj.getPropertyType().getTerrains().getTerrain().add(TerrainType.SEMINATIVO);
        obj.getPropertyType().setType(PropertyTypeSimple.CASA_INDIPENDENTE);

        obj.setTransactionType(FACTORY.createTransactionType());
        obj.getTransactionType().setAuction(RandomUtils.nextInt(0, 2) == 1);
        obj.getTransactionType().setOwnership(OwnershipType.PARZIALE);
        obj.getTransactionType().setValue("notes about transaction");

        obj.setVideos(FACTORY.createFeedPropertiesPropertyVideos());
        obj.getVideos().getVideo().add(createVideo());
        obj.getVideos().getVideo().add(createVideo());

        return obj;
    }

    /**
     * Create a {@link PictureProject} with some example data.
     *
     * @return created example object
     */
    protected static PictureProject createPicture() {
        PictureProject pic = FACTORY.createPictureProject();
        pic.setPosition(BigInteger.valueOf(RandomUtils.nextLong(0, 100)));
        pic.setValue("image-" + RandomUtils.nextInt(0, 999) + ".jpg");
        return pic;
    }

    /**
     * Create a {@link PictureExtended} with some example data.
     *
     * @return created example object
     */
    protected static PictureExtended createPictureExtended() {
        PictureExtended pic = FACTORY.createPictureExtended();
        pic.setPosition(BigInteger.valueOf(RandomUtils.nextLong(0, 100)));
        pic.setValue("image-" + RandomUtils.nextInt(0, 999) + ".jpg");
        pic.setUrl("http://mywebsite.org/" + pic.getValue());
        return pic;
    }

    /**
     * Create a {@link VideoProject} with some example data.
     *
     * @return created example object
     */
    protected static VideoProject createVideo() {
        VideoProject video = FACTORY.createVideoProject();
        video.setType(VideoType.LOCAL);
        video.setValue("video-" + RandomUtils.nextInt(0, 999) + ".mp4");
        return video;
    }

    /**
     * Write an {@link ImmobiliareItDocument} into a {@link File}.
     *
     * @param doc  the document to write
     * @param file the file, where the document is written to
     */
    @SuppressWarnings("Duplicates")
    protected static void write(ImmobiliareItDocument doc, File file) {
        LOGGER.info("writing document with version " + doc.getDocumentVersion());
        try {
            doc.toXml(file, PRETTY_PRINT);
            LOGGER.info("> written to: " + file.getAbsolutePath());
        } catch (Exception ex) {
            LOGGER.error("Can't write document into a file!");
            LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            System.exit(1);
        }
    }

    /**
     * Write an {@link ImmobiliareItDocument} into an {@link OutputStream}.
     *
     * @param doc    the document to write
     * @param output the stream, where the document is written to
     */
    @SuppressWarnings("Duplicates")
    protected static void write(ImmobiliareItDocument doc, OutputStream output) {
        LOGGER.info("writing document with version " + doc.getDocumentVersion());
        try {
            doc.toXml(output, PRETTY_PRINT);
            LOGGER.info("> written to a java.io.OutputStream");
        } catch (Exception ex) {
            LOGGER.error("Can't write document into an OutputStream!");
            LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            System.exit(1);
        }
    }

    /**
     * Write an {@link ImmobiliareItDocument} into a {@link Writer}.
     *
     * @param doc    the document to write
     * @param output the writer, where the document is written to
     */
    @SuppressWarnings("Duplicates")
    protected static void write(ImmobiliareItDocument doc, Writer output) {
        LOGGER.info("writing document with version " + doc.getDocumentVersion());
        try {
            doc.toXml(output, PRETTY_PRINT);
            LOGGER.info("> written to a java.io.Writer");
        } catch (Exception ex) {
            LOGGER.error("Can't write document into an OutputStream!");
            LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            System.exit(1);
        }
    }

    /**
     * Write an {@link ImmobiliareItDocument} into a {@link String} and print the
     * results to the console.
     *
     * @param doc the document to write
     */
    @SuppressWarnings("Duplicates")
    protected static void writeToConsole(ImmobiliareItDocument doc) {
        LOGGER.info("writing document with version " + doc.getDocumentVersion());
        try {
            String xml = doc.toXmlString(PRETTY_PRINT);
            LOGGER.info(StringUtils.repeat("-", 50)
                    + System.lineSeparator() + xml);
        } catch (Exception ex) {
            LOGGER.error("Can't write document into a string!");
            LOGGER.error("> " + ex.getLocalizedMessage(), ex);
            System.exit(1);
        }
    }
}


/*
 * Copyright 2015-2018 OpenEstate.org.
 *
 * 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.
 */
package org.openestate.io.examples.utils;

import org.apache.commons.text.CharacterPredicate;
import org.apache.commons.text.RandomStringGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Helper methods to generate random strings.
 *
 * @author Andreas Rudolph
 * @since 1.3
 */
public class RandomStringUtils {
    private final static Logger LOGGER = LoggerFactory.getLogger(RandomStringUtils.class);
    private final static CharacterPredicate NUMBERS = new CharacterPredicate() {
        @Override
        public boolean test(int codePoint) {
            // Accept codepoint from 0x30 to 0x39,
            // which represents a decimal digit in Unicode.
            return codePoint >= 0x30 && codePoint <= 0x39;
        }
    };
    private final static CharacterPredicate LETTERS = new CharacterPredicate() {
        @Override
        public boolean test(int codePoint) {
            // Accept codepoint from 0x41 to 0x5a or 0x61 to 0x7a,
            // which represents latin-1 characters in Unicode.
            return (codePoint >= 0x41 && codePoint <= 0x5a)
                    || (codePoint >= 0x61 && codePoint <= 0x7a);
        }
    };

    private RandomStringUtils() {
        super();
    }

    /**
     * Generate a random string with ASCII letters and digits.
     *
     * @param length length of the generated string
     * @return generated string
     */
    public static String random(int length) {
        return new RandomStringGenerator.Builder()
                .filteredBy(NUMBERS, LETTERS)
                .build().generate(length);
    }

    /**
     * Generate a random string with ASCII letters.
     *
     * @param length length of the generated string
     * @return generated string
     */
    public static String randomLetters(int length) {
        return new RandomStringGenerator.Builder()
                .filteredBy(LETTERS)
                .build().generate(length);
    }

    /**
     * Generate a random string with ASCII digits.
     *
     * @param length length of the generated string
     * @return generated string
     */
    public static String randomNumeric(int length) {
        return new RandomStringGenerator.Builder()
                .filteredBy(NUMBERS)
                .build().generate(length);
    }
}