View Javadoc

1   /*
2    * Copyright (c) 2014 by Oli B.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * (c)reated 08.08.2014 by Oli B. (ob@aosd.de)
17   */
18  
19  package gdv.xport.satz.xml;
20  
21  import gdv.xport.feld.AlphaNumFeld;
22  import gdv.xport.feld.Bezeichner;
23  import gdv.xport.feld.Feld;
24  import gdv.xport.satz.Teildatensatz;
25  
26  import java.util.ArrayList;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  import javax.xml.stream.XMLStreamException;
32  
33  import org.apache.logging.log4j.*;
34  
35  /**
36   * Dieser {@link Teildatensatz} wurde um Belange fuer die XML-Verarbeitung
37   * erweitert.
38   *
39   * @author oliver (oliver.boehm@gmail.com)
40   * @since 1.0 (08.08.2014)
41   */
42  public final class TeildatensatzXml extends Teildatensatz {
43  
44      private static final Logger LOG = LogManager.getLogger(TeildatensatzXml.class);
45      private static final Map<String, FeldXml> MISSING_FELDER = new HashMap<String, FeldXml>();
46      private final List<FeldReferenz> feldReferenzen = new ArrayList<FeldReferenz>();
47      private Satzende satzende;
48  
49      static {
50          try {
51              MISSING_FELDER.putAll(XmlService.getInstance("fehlendeFelder.xml").getFelder());
52          } catch (XMLStreamException ex) {
53              throw new IllegalArgumentException("cannot get missing felder from resource 'fehlendeFelder.xml'", ex);
54          }
55      }
56  
57      /**
58       * Instantiiert einen neuen Teildatensatz mit der angegebenen Satzart
59       * und Nummer.
60       *
61       * @param satzart z.B. 100
62       * @param nr Nummer des Teildatensatzes (zwischen 1 und 9)
63       */
64      public TeildatensatzXml(final int satzart, final int nr) {
65          super(satzart, nr);
66      }
67  
68      /**
69       * Verarbeitet die uebergebene {@link FeldReferenz}. Oder auch nicht.
70       *
71       * @param referenz the feld referenz
72       */
73      public void add(final FeldReferenz referenz) {
74          feldReferenzen.add(referenz);
75      }
76  
77      /**
78       * Setzt das Satzende
79       *
80       * @param satzende das Satzende
81       */
82      public void setSatzende(final Satzende satzende) {
83          this.satzende = satzende;
84      }
85  
86      /**
87       * Legt mithilfe der uebergebenen Felder die entsprechenden {@link Feld}-
88       * Objekte an. Aber nur, wenn ein Feld noch nicht existiert.
89       *
90       * @param felder Felder aus der XML-Beschreibung
91       */
92      public void updateWith(Map<String, FeldXml> felder) {
93          int byteAddress = 1;
94          for (FeldReferenz referenz : this.feldReferenzen) {
95              FeldXml feldXml = getFeld(felder, referenz.getId());
96              this.addFeld(feldXml, byteAddress, referenz.getBezeichner());
97              byteAddress += feldXml.getAnzahlBytes();
98          }
99          updateSatzendeWith(byteAddress, felder);
100         LOG.trace("{} felder set.", this.feldReferenzen.size());
101     }
102 
103     private FeldXml getFeld(Map<String, FeldXml> felder, String id) {
104         FeldXml feldXml = felder.get(id);
105         if (feldXml == null) {
106             LOG.info("Will try fallback for reference '{}'.", id);
107             feldXml = MISSING_FELDER.get(id);
108         }
109         if (feldXml == null) {
110             throw new IllegalArgumentException("reference '" + id + "' not found in " + felder);
111         }
112         return feldXml;
113     }
114 
115     private void updateSatzendeWith(final int startAddress, final Map<String, FeldXml> felder) {
116         List<FeldReferenz> referenzen = this.satzende.getFeldReferenzen();
117         int endAddress = 256;
118         for (int i = referenzen.size() - 1; i >= 0; i--) {
119             FeldReferenz referenz = referenzen.get(i);
120             FeldXml feldXml = felder.get(referenz.getId());
121             endAddress -= feldXml.getAnzahlBytes();
122             this.addFeld(feldXml, endAddress+1, referenz.getBezeichner());
123         }
124         int length = endAddress + 1 - startAddress;
125         if (length > 0) {
126             Feld leerstelle = new AlphaNumFeld((Bezeichner.LEERSTELLEN), endAddress + 1 - startAddress, startAddress);
127             this.add(leerstelle);
128         }
129     }
130 
131     private void addFeld(final FeldXml feldXml, final int byteAddress, final Bezeichner bezeichner) {
132         Feld feld = feldXml.toFeld(byteAddress, bezeichner);
133         if (!this.hasFeld(feld)) {
134             super.add(feld);
135         } else {
136             LOG.trace("{} not added again.", feld);
137         }
138     }
139 
140     /**
141      * Liefert die entsprechende {@link FeldReferenz}.
142      *
143      * @param bezeichner der gesuchte Bezeichner
144      * @return die gefundene {@link FeldReferenz}
145      */
146     public FeldReferenz getFeldRefenz(final Bezeichner bezeichner) {
147         for (FeldReferenz ref : this.feldReferenzen) {
148             if (bezeichner.equals(ref.getBezeichner())) {
149                 return ref;
150             }
151         }
152         throw new IllegalArgumentException(bezeichner + " not part of " + this);
153     }
154 
155 }