All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gdv.xport.satz.xml.SatzXml Maven / Gradle / Ivy

Go to download

gdv-xport-lib ist die Java-Bibliothek fuer den Umgang mit dem GDV-Format. Sie erleichtert den Export und Export dieses Datenformats.

The newest version!
/*
 * Copyright (c) 2014 by Oli B.
 *
 * 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 orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 30-Jul-2014 by Oli B. ([email protected])
 */

package gdv.xport.satz.xml;

import com.fasterxml.jackson.annotation.JsonIgnore;
import gdv.xport.config.Config;
import gdv.xport.satz.Datensatz;
import gdv.xport.util.SatzTyp;
import gdv.xport.util.XmlHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static gdv.xport.feld.Bezeichner.ART_580;
import static gdv.xport.feld.Bezeichner.WAGNISART;

/**
 * Im Gegensatz zum SOP-Ansatz und zur SatzX-Klasse wird hier eine XML-
 * Beschreibung verwendet, um die einzelnen Teildatensaetze mit ihren Feldern
 * zu bestimmen. Da die XML-Datei mit der Komplett-Beschreibung relativ gross
 * ist (ca. 7 MB), verwenden wir hier nicht einen DOM-Parser. Und auch keinen
 * XPath-Ansatz.
 *
 * @author oliver ([email protected])
 * @since 1.0 (30.07.2014)
 */
public class SatzXml extends Datensatz {

    private static final Logger LOG = LogManager.getLogger(SatzXml.class);

    /**
     * Instantiiert einen neuen Satz.
     *
     * @param parser XML-Event-Parser
     * @throws XMLStreamException the XML stream exception
     */
    public SatzXml(final XMLEventReader parser) throws XMLStreamException {
        this(parser, XmlHelper.getNextStartElement("satzart", parser), Config.getInstance());
    }

    /**
     * Instantiiert einen neuen Satz.
     *
     * @param parser XML-Event-Parser
     * @param element the element
     * @param config Konfiguration
     * @throws XMLStreamException the XML stream exception
     */
    public SatzXml(final XMLEventReader parser, final StartElement element, final Config config) throws XMLStreamException {
        super(SatzTyp.of(0), 0, config);
        parse(element, parser);
    }

    /**
     * Dies ist der Copy-Constructor, mit dem man einen bestehenden Satz
     * kopieren kann.
     *
     * @param orig der originale Satz
     */
    public SatzXml(final Datensatz orig) {
        super(orig);
    }

    private void parse(final StartElement element, final XMLEventReader reader) throws XMLStreamException {
        while (reader.hasNext()) {
            XMLEvent event = reader.nextEvent();
            if (event.isStartElement()) {
                parseElement(event.asStartElement(), reader);
            } else if (XmlHelper.isEndElement(event, element.getName())) {
                LOG.debug("{}...{} successful parsed.", element, event);
                return;
            }
            LOG.trace("Event {} is ignored.", event);
        }
        throw new XMLStreamException("end of " + element + " not found");
    }

  private void parseElement(final StartElement element, final XMLEventReader reader) throws XMLStreamException  {
    LOG.trace("Parsing element {}.", element);
    QName name = element.getName();

    if ("satzanfang".equals(name.getLocalPart()))  {
      parseTeildatensatz(element, reader);
    } else if ("feldreferenz".equals(name.getLocalPart()))  {
      parseFeldreferenz(element, reader);
    }
    else if ("version".equals(name.getLocalPart()))  {
      parseSatzversion(reader);
    }
  }

    private void parseTeildatensatz(final StartElement element, final XMLEventReader reader) throws XMLStreamException {
        TeildatensatzXml tds = parseSatzanfang(element, reader);
        while (reader.hasNext()) {
            XMLEvent event = reader.nextEvent();
            if (XmlHelper.isStartElement(event, "feldreferenz")) {
                tds.add(new FeldReferenz(reader, event.asStartElement()));
            } else if (XmlHelper.isStartElement(event, "satzende")) {
                LOG.trace("<{}> is reached.", element);
                tds.setSatzende(new Satzende(reader, event.asStartElement()));
                this.add(tds);
                return;
            }
        }
        throw new XMLStreamException(" for " + element + " not found");
    }

    private TeildatensatzXml parseSatzanfang(final StartElement element, final XMLEventReader reader) throws XMLStreamException {
        Attribute teilsatz = element.getAttributeByName(new QName("teilsatz"));
        int nr = Integer.parseInt(teilsatz.getValue());
        TeildatensatzXml tds = new TeildatensatzXml(this, nr);
        LOG.debug("Teildatensatz {} added to {}.", nr, this);
        while (reader.hasNext()) {
            XMLEvent event = reader.nextEvent();
            if (XmlHelper.isStartElement(event, "feldreferenz")) {
                tds.add(new FeldReferenz(reader, event.asStartElement()));
            } else if (XmlHelper.isEndElement(event, element.getName())) {
                LOG.trace("End of <{}> is reached.", element);
                return tds;
            }
        }
        throw new XMLStreamException("end of " + element + " not found");
    }

  private void parseFeldreferenz(StartElement element, final XMLEventReader reader) throws XMLStreamException  {
    FeldReferenz referenz = new FeldReferenz(reader, element);
    if (referenz.hasAuspraegung()) {
      if ("Satzart".equals(referenz.getName())) {
        this.getSatzartFeld().setInhalt(referenz.getAuspraegung());

        this.setGdvSatzartName(referenz.getAuspraegung());
      } else if ("Sparte".equals(referenz.getName())) {
        this.setSparte(referenz.getAuspraegung());

        this.setGdvSatzartName(referenz.getAuspraegung());
        LOG.debug("Sparte: {}", referenz.getAuspraegung());
      }
      else if ("Satznummer".equals(referenz.getName()))
      {
        //this.setGdvSatzartNummer(referenz.getAuspraegung());

        this.setGdvSatzartName(referenz.getAuspraegung());
        LOG.debug("Satznummer: {}", referenz.getAuspraegung());
      }
    }
  }

    private void parseSatzversion(XMLEventReader reader) throws XMLStreamException {
        if (reader.hasNext()) {
            XMLEvent event = reader.nextEvent();
            if (event.isCharacters()) {
                this.getSatzversion().setInhalt(event.asCharacters().getData());
            }
        }
    }

    /**
     * Setzen des Namens einer Gdv-Satzart.
     * 

* Der string wird mit dem Trennzeichen '.' an den bisherigen * Inhalt angehaengt. *

* * @param string Satzart-Name */ protected void setGdvSatzartName(String string) { StringBuilder buf = new StringBuilder(); if (this.getGdvSatzartName().isEmpty()) { buf.append(string); } else { buf.append(this.getGdvSatzartName()).append(".").append(string); } super.setGdvSatzartName(buf.toString()); } /** * Verwendet die uebergebene Map, um die Teildatensaetze um fehlende * Informationen zu ergaenzen. * * @param felder the felder */ public void setFelder(Map felder) { LOG.trace("Setting missing felder infos to {}.", this); for (int n = 1; n <= this.getNumberOfTeildatensaetze(); n++) { TeildatensatzXml tdsXml = (TeildatensatzXml) this.getTeildatensatz(n); tdsXml.updateWith(felder); updateSparte(tdsXml); } SatzTyp satzTyp = getSatzTyp(); if (satzTyp.hasWagnisart() && !getFeld(WAGNISART).hasValue()) { setFeld(WAGNISART, Integer.toString(satzTyp.getWagnisart()).substring(0, 1)); } else if (satzTyp.hasBausparenArt() && !getFeld(ART_580).hasValue()) { setFeld(ART_580, satzTyp.getBausparenArt()); } } private void updateSparte(TeildatensatzXml tdsXml) { if (tdsXml.hasSparte() && tdsXml.getSparte() == 0) { tdsXml.setSparte(getSatzTyp().getSparte()); } } /** * Liefert eine Liste der unterstuetzten Satz-Typen. Dies ist vor allem fuer * Satz 220 Sparte 10 von Bedeutung, die verschienden Wagnisarten * unterstuetzen koennen. * * @return the supported satz typen */ @JsonIgnore public List getSupportedSatzTypen() { List satzTypen = new ArrayList<>(); satzTypen.add(SatzTyp.of(this.getGdvSatzartName())); return satzTypen; } /** * Hier kann man mithilfe einer XML-Beschreibung einen Satz generieren. * Diese Methode dient dazu, um die Notwendigkeit der Enum-Beschreibung * weiter zu reduzieren. * * @param file Datei mit XML-Beschreibung * @return einen Satz gemaess der XML-Beschreibung * @throws IOException the io exception * @throws XMLStreamException the xml stream exception * @since 5.0 */ public static SatzXml of(File file) throws IOException, XMLStreamException { try (InputStream istream = new FileInputStream(file)) { return createSatzXml(istream); } } /** * Hier kann man mithile einer XML-Beschreibung einen Satz generieren. * Diese Methode dient dazu, um die Notwendigkeit der Enum-Beschreibung * weiter zu reduzieren. * * @param resource Classpath-Resource mit XML-Beschreibung * @return einen Satz gemaess der XML-Beschreibung * @throws IOException the io exception * @throws XMLStreamException the xml stream exception * @since 5.0 */ public static SatzXml of(String resource) throws IOException, XMLStreamException { try (InputStream istream = SatzXml.class.getResourceAsStream(resource)) { if (istream == null) { throw new IllegalArgumentException("not a resource: " + resource); } return createSatzXml(istream); } } /** * Im Gegensatz zu {@link SatzXml#of(String)} und {@link SatzXml#of(File)} * kann hier eine beliebige URI als Parameter uebergeben werden. Allerdings * werden momentan nur "classpath:" und "file:" als Protokoll unterstuetzt. * * @param resource URI der Resource (z.B. "classpath:/mein/satz.xml") * @return einen Satz gemaess der XML-Beschreibung * @throws IOException the io exception * @throws XMLStreamException the xml stream exception * @since 6.1 */ public static SatzXml of(URI resource) throws IOException, XMLStreamException { String scheme = resource.getScheme(); switch (scheme.toLowerCase()) { case "classpath": return of(resource.getPath()); case "file": return of(new File(resource)); default: throw new UnsupportedOperationException("Protokoll '" + scheme + "' wird (noch) nicht unterstuetzt"); } } private static SatzXml createSatzXml(InputStream istream) throws XMLStreamException { XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); XMLEventReader parser = xmlInputFactory.createXMLEventReader(istream); try { SatzXml satz = new SatzXml(parser); Map xmlFelder = XmlService.parseFelder(parser); satz.setFelder(xmlFelder); return satz; } finally { parser.close(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy