View Javadoc
1   /*
2    * Copyright (C) 2017 B3Partners B.V.
3    *
4    * This program is free software: you can redistribute it and/or modify
5    * it under the terms of the GNU Affero General Public License as published by
6    * the Free Software Foundation, either version 3 of the License, or
7    * (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU Affero General Public License for more details.
13   *
14   * You should have received a copy of the GNU Affero General Public License
15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16   */
17  package nl.b3p.brmo.loader.xml;
18  
19  import java.io.InputStream;
20  import java.io.StringWriter;
21  import java.util.Date;
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.Map.Entry;
25  import javax.xml.parsers.DocumentBuilder;
26  import javax.xml.parsers.DocumentBuilderFactory;
27  import javax.xml.parsers.ParserConfigurationException;
28  import javax.xml.transform.OutputKeys;
29  import javax.xml.transform.Source;
30  import javax.xml.transform.Templates;
31  import javax.xml.transform.Transformer;
32  import javax.xml.transform.TransformerFactory;
33  import javax.xml.transform.dom.DOMSource;
34  import javax.xml.transform.stream.StreamResult;
35  import javax.xml.transform.stream.StreamSource;
36  import javax.xml.xpath.XPath;
37  import javax.xml.xpath.XPathConstants;
38  import javax.xml.xpath.XPathExpression;
39  import javax.xml.xpath.XPathExpressionException;
40  import javax.xml.xpath.XPathFactory;
41  import nl.b3p.brmo.loader.BrmoFramework;
42  import nl.b3p.brmo.loader.StagingProxy;
43  import nl.b3p.brmo.loader.entity.Bericht;
44  import nl.b3p.brmo.loader.util.RsgbTransformer;
45  import org.w3c.dom.Document;
46  import org.w3c.dom.Node;
47  import org.w3c.dom.NodeList;
48  
49  /**
50   * @author Meine Toonen
51   */
52  public class BRPXMLReader extends BrmoXMLReader {
53  
54    private InputStream in;
55    private NodeList nodes = null;
56    private int index;
57  
58    private Templates template;
59    private final String pathToXsl = "/xsl/brp-brxml-preprocessor.xsl";
60  
61    public static final String PREFIX = "NL.BRP.Persoon.";
62    private StagingProxy staging;
63  
64    public BRPXMLReader(InputStream in, Date d, StagingProxy staging) throws Exception {
65      this.in = in;
66      this.staging = staging;
67      setBestandsDatum(d);
68      init();
69    }
70  
71    @Override
72    public void init() throws Exception {
73      soort = BrmoFramework.BR_BRP;
74      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
75      factory.setNamespaceAware(true);
76      factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
77      factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
78      factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
79      DocumentBuilder builder = factory.newDocumentBuilder();
80      Document doc = builder.parse(in);
81  
82      TransformerFactory tf = TransformerFactory.newInstance();
83      tf.setURIResolver(
84          (href, base) ->
85              new StreamSource(RsgbTransformer.class.getResourceAsStream("/xsl/" + href)));
86  
87      Source xsl = new StreamSource(BRPXMLReader.class.getResourceAsStream(pathToXsl));
88      this.template = tf.newTemplates(xsl);
89  
90      nodes = doc.getDocumentElement().getChildNodes();
91      index = 0;
92    }
93  
94    @Override
95    public boolean hasNext() throws Exception {
96      return index < nodes.getLength();
97    }
98  
99    @Override
100   public Bericht next() throws Exception {
101     Node n = nodes.item(index);
102     index++;
103     String object_ref = getObjectRef(n);
104     StringWriter sw = new StringWriter();
105     Bericht old =
106         staging.getPreviousBericht(object_ref, getBestandsDatum(), -1L, new StringBuilder());
107 
108     // kijk hier of dit bericht een voorganger heeft: zo niet, dan moet niet de preprocessor
109     // template gebruikt worden, maar de gewone.
110 
111     Transformer t;
112 
113     if (old != null) {
114       t = this.template.newTransformer();
115     } else {
116       t = TransformerFactory.newInstance().newTransformer();
117     }
118 
119     t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
120     t.transform(new DOMSource(n), new StreamResult(sw)); // new StreamResult(outputStream));
121 
122     Map<String, String> bsns = extractBSN(n);
123 
124     String el = getXML(bsns);
125     String origXML = sw.toString();
126     String brXML = "<root>" + origXML;
127     brXML += el + "</root>";
128     Bericht b = new Bericht(brXML);
129     b.setBrOrgineelXml(origXML);
130     b.setVolgordeNummer(index);
131     b.setObjectRef(object_ref);
132     b.setSoort(BrmoFramework.BR_BRP);
133     b.setDatum(getBestandsDatum());
134     return b;
135   }
136 
137   private String getObjectRef(Node n) {
138     NodeList childs = n.getChildNodes();
139     String hash = null;
140     for (int i = 0; i < childs.getLength(); i++) {
141       Node child = childs.item(i);
142       String name = child.getNodeName();
143       if (name.contains("bsn-nummer")) {
144         hash = child.getTextContent();
145         hash = getHash(hash);
146         break;
147       }
148     }
149     return PREFIX + hash;
150   }
151 
152   /**
153    * maakt een map met bsn,bsnhash.
154    *
155    * @param n document node met bsn-nummer
156    * @return hashmap met bsn,bsnhash
157    * @throws XPathExpressionException if any
158    */
159   public Map<String, String> extractBSN(Node n) throws XPathExpressionException {
160     Map<String, String> hashes = new HashMap<>();
161 
162     XPathFactory xPathfactory = XPathFactory.newInstance();
163     XPath xpath = xPathfactory.newXPath();
164     XPathExpression expr = xpath.compile("//*[local-name() = 'bsn-nummer']");
165     NodeList nodelist = (NodeList) expr.evaluate(n, XPathConstants.NODESET);
166     for (int i = 0; i < nodelist.getLength(); i++) {
167       Node bsn = nodelist.item(i);
168       String bsnString = bsn.getTextContent();
169       String hash = getHash(bsnString);
170       hashes.put(bsnString, hash);
171     }
172     return hashes;
173   }
174 
175   public String getXML(Map<String, String> map) throws ParserConfigurationException {
176     String root = "<bsnhashes>";
177     for (Entry<String, String> entry : map.entrySet()) {
178       if (!entry.getKey().isEmpty() && !entry.getValue().isEmpty()) {
179         String hash = entry.getValue();
180 
181         String el =
182             "<" + PREFIX + entry.getKey() + ">" + hash + "</" + PREFIX + entry.getKey() + ">";
183         root += el;
184       }
185     }
186     root += "</bsnhashes>";
187     return root;
188   }
189 }