Java tutorial
/* * Copyright 2015-2016 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.List; 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.OpenImmoVersion; import org.openestate.io.openimmo.OpenImmoDocument; import org.openestate.io.openimmo.OpenImmoFeedbackDocument; import org.openestate.io.openimmo.OpenImmoTransferDocument; 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.4. * * @since 1.0 * @author Andreas Rudolph */ public class OpenImmo_1_2_4 extends XmlConverter<OpenImmoDocument, OpenImmoVersion> { private final static Logger LOGGER = LoggerFactory.getLogger(OpenImmo_1_2_4.class); @Override public OpenImmoVersion getVersion() { return OpenImmoVersion.V1_2_4; } /** * Downgrade an OpenImmo document from version 1.2.4 to 1.2.3. * * @param doc OpenImmo document in version 1.2.4 */ @Override public void downgradeToPreviousVersion(OpenImmoDocument doc) { doc.setDocumentVersion(OpenImmoVersion.V1_2_3); // downgrade a feedback document if (doc instanceof OpenImmoFeedbackDocument) { try { this.removeFeedbackVersionElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't remove unsupported <version> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } try { this.removeFeedbackInteressentChildElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't remove unsupported children of <interessent> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } } // downgrade a transfer document else if (doc instanceof OpenImmoTransferDocument) { try { this.removePreiseChildElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't remove unsupported children of <preise> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } try { this.removeWintergartenElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't remove unsupported <wintergarten> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } try { this.downgradeEnergietypElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't downgrade <energietyp> 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.downgradeAnhangElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't downgrade <anhang> 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.downgradeGrundstueckElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't downgrade <grundstueck> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } try { this.downgradeLandUndForstwirtschaftElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't downgrade <land_und_forstwirtschaft> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } try { this.downgradeParkenElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't downgrade <parken> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } } } /** * Upgrade an OpenImmo document from version 1.2.3 to 1.2.4. * * @param doc OpenImmo document in version 1.2.3 */ @Override public void upgradeFromPreviousVersion(OpenImmoDocument doc) { doc.setDocumentVersion(OpenImmoVersion.V1_2_4); if (doc instanceof OpenImmoTransferDocument) { try { this.upgradeAnzahlBalkonTerrassenElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't upgrade <anzahl_balkon_terrassen> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } try { this.upgradeAnhangElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't upgrade <anhang> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } try { this.upgradeSonstigeElements(doc.getDocument()); } catch (Exception ex) { LOGGER.error("Can't upgrade <sonstige> elements!"); LOGGER.error("> " + ex.getLocalizedMessage(), ex); } } } /** * Downgrade <anhang> elements to OpenImmo 1.2.3. * <p> * The options "QRCODE", "FILM", "FILMLINK" for the "gruppe" attribute of * <anhang> elements are not available in version 1.2.3. * <p> * The option "REMOTE" for the "location" attribute of * <anhang> elements is not available in version 1.2.3. * <p> * The the child element <check> of <anhang> elements is not * available in version 1.2.3. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ protected void downgradeAnhangElements(Document doc) throws JaxenException { List nodes = XmlUtils.newXPath("/io:openimmo/io:anbieter/io:anhang | " + "/io:openimmo/io:anbieter/io:immobilie/io:anhaenge/io:anhang", doc).selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; String value = StringUtils.trimToNull(node.getAttribute("gruppe")); if ("QRCODE".equalsIgnoreCase(value)) node.removeAttribute("gruppe"); else if ("FILM".equalsIgnoreCase(value)) node.removeAttribute("gruppe"); else if ("FILMLINK".equalsIgnoreCase(value)) node.removeAttribute("gruppe"); value = StringUtils.trimToNull(node.getAttribute("location")); if ("REMOTE".equalsIgnoreCase(value)) node.setAttribute("location", "EXTERN"); List childNodes = XmlUtils.newXPath("io:check", doc).selectNodes(node); for (Object childItem : childNodes) { node.removeChild((Node) childItem); } } } /** * Downgrade <bebaubar_nach> elements to OpenImmo 1.2.3. * <p> * The option "LAENDERSPEZIFISCH" for the "bebaubar_attr" attribute of * <bebaubar_nach> elements is not available in version 1.2.3. * <p> * Any occurences of these values are removed. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ 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 ("LAENDERSPEZIFISCH".equalsIgnoreCase(value)) node.removeAttribute("bebaubar_attr"); } } /** * Downgrade <energietyp> elements to OpenImmo 1.2.3. * <p> * The attributes "KFW55", "KFW70" of <energietyp> elements are not * available in OpenImmo 1.2.3. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ protected void downgradeEnergietypElements(Document doc) throws JaxenException { List nodes = XmlUtils .newXPath("/io:openimmo/io:anbieter/io:immobilie/io:ausstattung/io:energietyp[@KFW55 or @KFW70]", doc) .selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; node.removeAttribute("KFW55"); node.removeAttribute("KFW70"); } } /** * Downgrade <grundstueck> elements to OpenImmo 1.2.3. * <p> * The option "SEELIEGENSCHAFT" for the "grundst_typ" attribute of * <grundstueck> elements is not available in version 1.2.3. * <p> * Any occurence of these values is removed. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ protected void downgradeGrundstueckElements(Document doc) throws JaxenException { List nodes = XmlUtils.newXPath( "/io:openimmo/io:anbieter/io:immobilie/io:objektkategorie/io:objektart/io:grundstueck[@grundst_typ]", doc).selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; String value = StringUtils.trimToNull(node.getAttribute("grundst_typ")); if ("SEELIEGENSCHAFT".equalsIgnoreCase(value)) node.removeAttribute("grundst_typ"); } } /** * Downgrade <land_und_forstwirtschaft> elements to OpenImmo 1.2.3. * <p> * The option "JAGDREVIER" for the "land_typ" attribute of * <land_und_forstwirtschaft> elements is not available in version * 1.2.3. * <p> * Any occurence of these values is replaced by the * "SONSTIGE_LANDWIRTSCHAFTSIMMOBILIEN" value. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ protected void downgradeLandUndForstwirtschaftElements(Document doc) throws JaxenException { List nodes = XmlUtils.newXPath( "/io:openimmo/io:anbieter/io:immobilie/io:objektkategorie/io:objektart/io:land_und_forstwirtschaft[@land_typ]", doc).selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; String value = StringUtils.trimToNull(node.getAttribute("land_typ")); if ("JAGDREVIER".equalsIgnoreCase(value)) node.setAttribute("land_typ", "SONSTIGE_LANDWIRTSCHAFTSIMMOBILIEN"); } } /** * Downgrade <parken> elements to OpenImmo 1.2.3. * <p> * The options "EINZELGARAGE", "PARKHAUS", "TIEFGARAGENSTELLPLATZ", * "PARKPLATZ_STROM" for the "parken_typ" attribute of * <parken> elements are not available in version 1.2.3. * <p> * Any occurence of these values is replaced by the "STELLPLATZ" value. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ protected void downgradeParkenElements(Document doc) throws JaxenException { List nodes = XmlUtils.newXPath( "/io:openimmo/io:anbieter/io:immobilie/io:objektkategorie/io:objektart/io:parken[@parken_typ]", doc) .selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; String value = StringUtils.trimToNull(node.getAttribute("parken_typ")); if ("EINZELGARAGE".equalsIgnoreCase(value)) node.setAttribute("parken_typ", "STELLPLATZ"); else if ("PARKHAUS".equalsIgnoreCase(value)) node.setAttribute("parken_typ", "STELLPLATZ"); else if ("TIEFGARAGENSTELLPLATZ".equalsIgnoreCase(value)) node.setAttribute("parken_typ", "STELLPLATZ"); else if ("PARKPLATZ_STROM".equalsIgnoreCase(value)) node.setAttribute("parken_typ", "STELLPLATZ"); } } /** * Downgrade <wohnung> elements to OpenImmo 1.2.3. * <p> * The option "ROHDACHBODEN" for the "wohnungtyp" attribute of * <wohnung> elements is not available in version 1.2.3. * <p> * Any occurence of these values is replaced by the "KEINE_ANGABE" value. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ 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 ("ROHDACHBODEN".equalsIgnoreCase(value)) node.setAttribute("wohnungtyp", "KEINE_ANGABE"); } } /** * Remove unsupported children from all <interessent> elements in * feedback XML. * <p> * OpenImmo 1.2.3 does not support more then one <bevorzugt>, * <wunsch> elements in feedback XML. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ protected void removeFeedbackInteressentChildElements(Document doc) throws JaxenException { List nodes = XmlUtils.newXPath("/io:openimmo_feedback/io:objekt/io:interessent", doc).selectNodes(doc); for (Object item : nodes) { Element parentNode = (Element) item; boolean bevorzugtPassed = false; boolean wunschPassed = false; List childNodes = XmlUtils.newXPath("io:bevorzugt", doc).selectNodes(parentNode); for (Object childItem : childNodes) { Element node = (Element) childItem; if (!bevorzugtPassed) bevorzugtPassed = true; else parentNode.removeChild(node); } childNodes = XmlUtils.newXPath("io:wunsch", doc).selectNodes(parentNode); for (Object childItem : childNodes) { Element node = (Element) childItem; if (!wunschPassed) wunschPassed = true; else parentNode.removeChild(node); } } } /** * Remove <version> elements in feedback XML. * <p> * OpenImmo 1.2.3 does not support <version> elements in feedback XML. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ protected void removeFeedbackVersionElements(Document doc) throws JaxenException { List nodes = XmlUtils.newXPath("/io:openimmo_feedback/io:version", doc).selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; Element parentNode = (Element) node.getParentNode(); parentNode.removeChild(node); } } /** * Remove unsupported children from all <preise> elements. * <p> * OpenImmo 1.2.3 does not support the following children for * <preise> elements: <provision_teilen>, <kaution_text>, * <richtpreis> * <p> * These elements are removed by this function. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ protected void removePreiseChildElements(Document doc) throws JaxenException { List nodes = XmlUtils.newXPath("/io:openimmo/io:anbieter/io:immobilie/io:preise/io:provision_teilen | " + "/io:openimmo/io:anbieter/io:immobilie/io:preise/io:kaution_text | " + "/io:openimmo/io:anbieter/io:immobilie/io:preise/io:richtpreis", doc).selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; Element parentNode = (Element) node.getParentNode(); parentNode.removeChild(node); } } /** * Remove <wintergarten> elements. * <p> * OpenImmo 1.2.3 does not support <wintergarten> elements. * * @param doc OpenImmo document in version 1.2.4 * @throws JaxenException */ protected void removeWintergartenElements(Document doc) throws JaxenException { List nodes = XmlUtils.newXPath("/io:openimmo/io:anbieter/io:immobilie/io:ausstattung/io:wintergarten", doc) .selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; Element parentNode = (Element) node.getParentNode(); parentNode.removeChild(node); } } /** * Upgrade <anhang> elements to OpenImmo 1.2.4. * <p> * The option "REMOTE" for the "location" attribute of <anhang> elements * is introduced with OpenImmo 1.2.4. * <p> * If the <pfad> element of an <anhang> element contains an URL * (beginning with "http://" / "https://" / "ftp://" / "ftps://"), the value * of the "location" attribute is changed to "REMOTE". * * @param doc OpenImmo document in version 1.2.3 * @throws JaxenException */ protected void upgradeAnhangElements(Document doc) throws JaxenException { List nodes = XmlUtils .newXPath( "/io:openimmo/io:anbieter/io:anhang/io:daten/io:pfad | " + "/io:openimmo/io:anbieter/io:immobilie/io:anhaenge/io:anhang/io:daten/io:pfad", doc) .selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; Element parentNode = (Element) node.getParentNode().getParentNode(); String value = StringUtils.trimToEmpty(node.getTextContent()).toLowerCase(); if (value.startsWith("http://")) parentNode.setAttribute("location", "REMOTE"); else if (value.startsWith("https://")) parentNode.setAttribute("location", "REMOTE"); else if (value.startsWith("ftp://")) parentNode.setAttribute("location", "REMOTE"); else if (value.startsWith("ftps://")) parentNode.setAttribute("location", "REMOTE"); } } /** * Upgrade <anzahl_balkon_terrassen> elements to OpenImmo 1.2.4. * <p> * The <anzahl_balkon_terrassen> is not supported anymore in version * 1.2.4. The element is replaced by <anzahl_balkone> and * <anzahl_terrassen>. * <p> * Any <anzahl_balkon_terrassen> element is removed. Its content is * copied into <anzahl_balkone>, if this element is not already present. * * @param doc OpenImmo document in version 1.2.3 * @throws JaxenException */ protected void upgradeAnzahlBalkonTerrassenElements(Document doc) throws JaxenException { List nodes = XmlUtils .newXPath("/io:openimmo/io:anbieter/io:immobilie/io:flaechen/io:anzahl_balkon_terrassen", doc) .selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; Element parentNode = (Element) node.getParentNode(); String value = StringUtils.trimToNull(node.getTextContent()); if (value != null) { Element newNode = (Element) XmlUtils.newXPath("io:anzahl_balkone", doc) .selectSingleNode(parentNode); if (newNode == null) { newNode = doc.createElementNS(StringUtils.EMPTY, "anzahl_balkone"); newNode.setTextContent(value); parentNode.appendChild(newNode); } else if (StringUtils.isBlank(newNode.getTextContent())) { newNode.setTextContent(value); } } parentNode.removeChild(node); } } /** * Upgrade <sonstige> elements to OpenImmo 1.2.4. * <p> * The options "GARAGEN", "PARKFLACHE" for the "sonstige_typ" attribute of * <sonstige> elements were removed with OpenImmo 1.2.4. * <p> * For any occurence of these values the corresponding <sonstige> * element is replaced with a <parken> element. * * @param doc OpenImmo document in version 1.2.3 * @throws JaxenException */ protected void upgradeSonstigeElements(Document doc) throws JaxenException { List nodes = XmlUtils.newXPath( "/io:openimmo/io:anbieter/io:immobilie/io:objektkategorie/io:objektart/io:sonstige[@sonstige_typ]", doc).selectNodes(doc); for (Object item : nodes) { Element node = (Element) item; String value = StringUtils.trimToNull(node.getAttribute("sonstige_typ")); if ("GARAGEN".equalsIgnoreCase(value) || "PARKFLACHE".equalsIgnoreCase(value)) { Element parentNode = (Element) node.getParentNode(); parentNode.removeChild(node); Element newNode = doc.createElementNS(StringUtils.EMPTY, "parken"); newNode.setAttribute("parken_typ", "STELLPLATZ"); parentNode.appendChild(newNode); } } } }